Вы можете делать то, что вы хотите, но не с вашим текущим подходом. Давайте сделаем шаг назад. Что является исключением таблицы мутаций (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;