Составные триггеры - PullRequest
0 голосов
/ 05 марта 2020

Проблема - Хотите избежать проблемы с мутацией триггеров, используя составной триггер. Но не в состоянии сделать это

Справочная информация - я хочу вставить данные в новую таблицу «Таблица отслеживания» при каждом изменении в основной таблице «CUSTOM_ITEM»

Дизайн таков, что каждый раз, когда строка созданный в таблице ITEM_ID генерируется, но есть столбец FIRST_ITEM_ID, который в некоторых случаях остается таким же.

Поэтому, когда добавляется новая строка, я хочу проверить ее FIRST_ITEM_ID, а затем проверить всю таблицу и выяснить все ITEM_ID с таким же FIRST_ITEM_ID.

И я хочу вставить все эти строки в новой таблице с использованием триггера.

Возможно ли это вообще?

Подключение триггера:

CREATE OR REPLACE TRIGGER APP.TEST_TRG
FOR DELETE OR INSERT OR UPDATE 
ON APP.CUSTOM_ITEM
COMPOUND TRIGGER

TYPE t_change_tab IS TABLE OF APP.TEST_TRG.OBJECT_ID%TYPE;
g_change_tab t_change_tab := t_change_tab();

BEFORE EACH ROW IS
  BEGIN


      Select item_id bulk collect into g_change_tab from CUSTOM_ITEM where first_item_id =
     (Select first_item_id from CUSTOM_ITEM where item_id = :NEW.item_id);


        For i in 1 .. g_change_tab.COUNT()
            LOOP 

            g_change_tab.extend;

            END LOOP;    

  END BEFORE EACH ROW;

AFTER STATEMENT IS

    BEGIN
    For i in 1 .. g_change_tab.COUNT()
    LOOP

        app.bc_acs_pkg.populate_TEST_TRG     /* Package Inserts data */
                (p_object_type => 'ITEM',
                p_object_id => g_change_tab(i));


    END LOOP;

    g_change_tab.delete;
  END AFTER STATEMENT;


END ;
/

1 Ответ

0 голосов
/ 05 марта 2020

Вы можете делать то, что вы хотите, но не с вашим текущим подходом. Давайте сделаем шаг назад. Что является исключением таблицы мутаций (ORA-04091). Выдается при попытке доступа к таблице, по которой сработал триггер в событии уровня строки, что недопустимо. Простое создание составного триггера не снимает это ограничение. Таким образом, в вашем сегменте «Перед строкой» оператор

Select item_id 
  bulk collect into g_change_tab 
  from CUSTOM_ITEM where first_item_id =
     (Select first_item_id from CUSTOM_ITEM where item_id = :NEW.item_id);

недопустим и приводит к повышению ORA-04091. Что вам нужно, это просто собрать свою коллекцию с необходимыми идентификаторами. Затем обработайте их в сегменте оператора After.

create or replace trigger test_trg
for delete or insert or update 
on custom_item
compound trigger
  type t_change_tab is 
       table of custom_item.first_item%type; 

  g_change_tab t_change_tab := t_change_tab();

before each row is
      l_first_item_exists boolean := false;
      indx                integer; 
  begin
      indx := g_change_tab.first;  
      while not l_first_item_exists
        and indx is not null 
      loop
          l_first_item_exists := (g_change_tab(indx) = :new.first_item);
          if not l_first_item_exists
          then 
              indx := g_change_tab.next(indx);
          end if;               
      end loop; 

      if not l_first_item_exists
      then
        g_change_tab.extend;
        g_change_tab(g_change_tab.last) := :new.first_item;
      end if; 
end before each row;

after statement is
  begin
     for indx in g_change_tab.first .. g_change_tab.last
     loop 
         insert into tracking_table(item_id, first_item)
         select item_id, first_item
           from custom_item 
          where first_item = g_change_tab(indx);
     end loop;
end after statement;
end test_trg;

Проблема здесь в циклах, всегда самая медленная обработка и очень плохие триггеры. Ниже приведен подход, который полностью их избегает. Однако для этого требуется создать массив типов на уровне схемы.

create or replace type custom_item_change_t is 
                   table of integer ; --custom_item.first_item%type;

create or replace trigger test_trg
for insert
on custom_item
compound trigger     
  g_change_tab custom_item_change_t := custom_item_change_t();

before each row is
  begin
    g_change_tab.extend;
    g_change_tab(g_change_tab.last) := :new.first_item; 
end before each row;

after statement is
  begin
   insert into tracking_table(item_id, first_item)
     select item_id, first_item
       from custom_item ci
      where first_item in (select distinct column_value
                             from table(g_change_tab)
                          ) 
        and not exists 
            ( select null 
                from tracking_table tt
               where ci.item_id = tt.item_id
                 and ci.first_item = tt.first_item
            ); 
end after statement;
end test_trg;       
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...