Problem - Want to avoid the problem of mutating triggers by using the compound trigger. But unable to do so
Background - I want to insert data in new table " Tracking Table " whenever there is change in Main table "CUSTOM_ITEM"
Design is such that, everytime a row is created in table an ITEM_ID is generated but there is a column FIRST_ITEM_ID that remains same in some cases.
So whenever a new row is added, I want to check its FIRST_ITEM_ID and then check the whole table and find out all the ITEM_IDs having that same FIRST_ITEM_ID.
And I want to insert all those rows in the New table using trigger.
Is it even possible ?
Attaching the trigger :
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 ;
/
You can do what you want just not with your current approach. Let's take a step back. What is a mutating table exception (ORA-04091). It is thrown when you attempt to access the table on which the trigger fired in a row level event, that is not permitted. Just creating a compound trigger does not remove that restriction. So in your Before Row segment the statement
is invalid, and results in raising ORA-04091. What you need is to just build your collection with the necessary ids. Then process them in the After statement segment.
The issue here is the loops, always the slowest processing, and very bad in triggers. Below is an approach which avoids them totally. It does however require creating your type array at the schema level.