Объединение 2 блоков if и создание единого запроса

Aug 20 2020

Есть ли возможность объединить блок if и создать единый блок снизу. Оба логически связаны.

Если p_update_mode is FUll, то мне нужно добавить все данные таблицы, переданные для P_entity_type. если он инкрементный, я поставил условие соединения для добавления выбранного добавления. также, если p_entity_type имеет значение null, мы должны добавить данные как для таблиц элементов, так и для организационных таблиц.

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) = 'incremental'
  THEN
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    WITH data_view AS
     ( -- ITEM table
      SELECT 'ITEM' entity_type, -- This separates inserted values
              item_id data_id,
              item_name data_name,
              item_desc data_desc,
              creation_date
        FROM itemde
      UNION ALL
      -- ORG table
      SELECT 'ORG' entity_type, -- This separates inserted values
              org_id,
              org_name,
              org_desc,
              creation_date
        FROM orgde
      -- NEXT entity table
      )
    SELECT upper(t.entity_type),
           t.data_id,
           t.data_name,
           t.data_desc,
           CASE
             WHEN t.creation_date > b.max_last_update_date THEN
               'update'
             WHEN t.creation_date < b.max_last_update_date THEN
               'add'
           END
      FROM data_view t
      JOIN batch_run_details b
        ON b.entity_type = t.entity_type
     WHERE upper(p_entity_type) = t.entity_type
        OR p_entity_type IS NULL;
  
 END IF;
 
 IF UPPER(UPDATE_MODE)='FULL' then
   
    INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    WITH data_view AS
     ( 
      SELECT 'ITEM' entity_type, -- This separates inserted values
              item_id data_id,
              item_name data_name,
              item_desc data_desc,
              'add' action
        FROM itemde
      UNION ALL
      -- ORG table
      SELECT 'ORG' entity_type, -- This separates inserted values
              org_id,
              org_name,
              org_desc,
              'add' action
        FROM orgde
      )
    SELECT upper(entity_type), data_id, data_name, data_desc,action
      FROM data_view
     WHERE upper(p_entity_type) = entity_type
        OR p_entity_type IS NULL;
    END IF;
        
END update_dynamic_entity;

Ответы

2 KevinMcCabe Aug 21 2020 at 04:58

(ПРИМЕЧАНИЕ: этот код не тестировался, и я могу не ставить запятую здесь или скобки там ...)

Кажется, что эти два блока различаются только столбцом действия и соединением, поэтому вы можете исключить 2 ветви IF и переместить проверку p_update_mode в оператор CASE следующим образом:

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    WITH data_view AS
     ( -- ITEM table
      SELECT 'ITEM' entity_type, -- This separates inserted values
              item_id data_id,
              item_name data_name,
              item_desc data_desc,
              creation_date
        FROM itemde
      UNION ALL
      -- ORG table
      SELECT 'ORG' entity_type, -- This separates inserted values
              org_id,
              org_name,
              org_desc,
              creation_date
        FROM orgde
      -- NEXT entity table
      )
    SELECT upper(t.entity_type),
           t.data_id,
           t.data_name,
           t.data_desc,
           CASE lower(p_update_mode)
             WHEN 'incremental' THEN
               CASE
                 WHEN t.creation_date > b.max_last_update_date THEN
                   'update'
                 WHEN t.creation_date < b.max_last_update_date THEN
                   'add'
               END
             WHEN 'full' THEN
              'add' 
           END action
      FROM data_view t
           LEFT JOIN batch_run_details b
                  ON b.entity_type = t.entity_type
                 AND lower(p_update_mode )='incremental'
     WHERE (upper(p_entity_type) = t.entity_type OR p_entity_type IS NULL)
       AND (lower(p_update_mode) = 'full'
            OR (lower(p_update_mode) = 'incremental' AND b.entity_type IS NOT NULL)
           );
        
END update_dynamic_entity;

Запрос в вашем FULL-блоке говорит, что мы не должны присоединяться к B в этом режиме. Таким образом, предложение LEFT JOIN возвращает строки только в режиме INCREMENTAL, но не должно создавать строк для режима FULL.

Это должно быть ЛЕВОЕ соединение, иначе мы не сможем получить какие-либо строки из вашего data_view, которые не соответствуют объектам в B для FULL режима. Другими словами, если бы это оставалось обычным JOIN, ваш общий запрос получил бы ноль строк в режиме FULL из-за предложения AND в соединении.

Наконец, теперь, когда есть LEFT JOIN, необходим фильтр AND в предложении WHERE внизу. Без этого при работе в режиме INCREMENTAL вы получите КАЖДУЮ строку в вашем data_view НЕЗАВИСИМО от того, есть соответствующая строка объекта в B или нет. Даже если вы присоединяетесь к entity_id, левое соединение будет возвращать строку для каждой строки в T даже без соответствующей строки в B, потому что именно для этого были разработаны LEFT JOIN.

С учетом всего сказанного вам нужно будет решить, стоит ли смешивать эти два блока. То, что вы МОЖЕТЕ, не означает, что вы ДОЛЖНЫ. Ваша производительность может быть лучше, если оставить все как есть - запустите несколько тестов. Только вы знаете объем данных и частоту обработки. Вам также необходимо подумать о поддержке вашего кода, так как следующему парню / девушке придется разобраться, что здесь происходит.