plsql процедура повторяющаяся строка кода. пытаясь сделать лучше

Aug 21 2020

У меня есть сценарий. Если пользователь передает параметр, Entity_typeвам нужно вставить данные только для этого entity( table). Если он не передает ни одного параметра, вам нужно вставить данные для всех необходимых таблиц в одну таблицу.

Итак, у нас есть таблица, DYNAMICENTITYGTTкоторая будет брать данные из Itemтаблицы, если она передана, orgтаблица, если она передана. Но он будет брать данные из обеих таблиц, если в процессе Entity_typeпараметр имеет значение null.

Также он будет хранить другой столбец в зависимости от типа UPDATE_MODEсредств добавления или удаления. Целевая таблица такая же. Исходная таблица и имя ее столбца отличаются, но тип одинаков.

Я написал ниже процедуру для того же.

Я всего лишь прошу, есть ли способ улучшить этот код. Я имею в виду, можно ли это написать более умным способом? Потому что я повторяю несколько строк. Я привел пример двух сущностей, но их семь, поэтому код будет огромным.

CREATE OR REPLACE procedure UPDATE_DYNAMIC_ENTITY(ENTITY_TYPE varchar2 default null,UPDATE_MODE varchar2)
Is
x number;
BEGIN
IF UPPER(entity_type)='ITEM' then
    if upper(UPDATE_MODE)='DELETE' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'delete' from ITEMDE;
    ELSIF lower(UPDATE_MODE)='add' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'add' from ITEMDE;
    END IF;
ELSIF UPPER(entity_type)='ORG' then
    if upper(UPDATE_MODE)='DELETE' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'delete' from ORGDE;
    ELSIF lower(UPDATE_MODE)='add' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'add' from ORGDE;
    END IF;
ELSE
   if upper(UPDATE_MODE)='DELETE' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'delete' from ITEMDE;
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'delete' from ORGDE;
    ELSIF lower(UPDATE_MODE)='add' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'add' from ITEMDE;
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'add' from ORGDE;
   END IF;
   
END IF;
END UPDATE_DYNAMIC_ENTITY;

Ответы

1 KayaNatsumi Aug 20 2020 at 22:10

В основном я вижу две вставки с двумя переменными, определяющими его содержимое. Вы вставляете из оператора select, поэтому вы можете манипулировать этими выборками, чтобы не возвращать значения, когда условия не соответствуют ожидаемым.

Для параметра p_update_modeэто просто, если он содержит значение «удалить» вставить «удалить», если он содержит значение «добавить» вставить «добавить».

Для параметра p_entity_typeмы вставляем оба выбора, когда его значение равно «NULL», только из itemdeтаблицы, если значение равно «ITEM», и только из orgdeтаблицы, если значение равно «ORG».

Теперь, если есть какое-то недопустимое значение, p_entity_typeни один из выборок не приведет к получению данных, поскольку мы распознаем только «NULL», «ITEM» и «ORG». Но для параметра p_update_modeмы напрямую изменяем значение и используем его во вставке, поэтому было бы лучше выполнить некоторую проверку, действительно ли введенное значение для нас.

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) NOT IN ('add', 'delete')
  THEN
    RAISE VALUE_ERROR; -- maybe use raise_application_error for more details about problem
  END IF;
  --
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    SELECT upper(NVL(p_entity_type, 'ITEM')), item_id, item_name, item_desc, lower(p_update_mode)
      FROM itemde
     WHERE upper(p_entity_type) = 'ITEM'
        OR p_entity_type IS NULL;
  --
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    SELECT upper(NVL(p_entity_type, 'ORG')), org_id, org_name, org_desc, lower(p_update_mode)
      FROM orgde
     WHERE upper(p_entity_type) = 'ORG'
        OR p_entity_type IS NULL;
END update_dynamic_entity;

Когда вы пишете, у вас есть 7 сущностей, поэтому этот подход приведет к 7 вставкам, поскольку я считаю (и дайте мне знать, если я ошибаюсь) каждая сущность имеет свой собственный набор данных в разных таблицах.

Существует также возможность объединить все эти таблицы и превратить их в одну вставку, как в примере ниже, и каждая новая сущность будет означать только добавление нового выбора в WITHчасть оператора. Но я не уверен в производительности в этом случае. Это будет зависеть от того, насколько заполнены ваши столы.

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) NOT IN ('add', 'delete')
  THEN
    RAISE VALUE_ERROR; -- maybe use raise_application_error for more details about problem
  END IF;
  --
  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
        FROM itemde
      UNION ALL
      -- ORG table
      SELECT 'ORG' entity_type, -- This separates inserted values
              org_id,
              org_name,
              org_desc
        FROM orgde
      -- NEXT entity table
      )
    SELECT upper(entity_type), data_id, data_name, data_desc, lower(p_update_mode)
      FROM data_view
     WHERE upper(p_entity_type) = entity_type
        OR p_entity_type IS NULL;
END update_dynamic_entity;

И даже если это станет для вас запутанным, вы можете создать область, в VIEWкоторой вы выполняете UNIONоперации, и удалить ее WITHиз PROCEDUREновых сущностей, добавляя выборки VIEWвместо PROCEDURE.