You are on page 1of 9

Ads by Go o gle

Oracle JDBC

Oracle 11G

Ho me

Articles

Scripts

Fo rums

Blo g

Certificatio n

Misc

Search

Abo ut

Printer Friendly

Oracle 8i | Oracle 9i | Oracle 10g | Oracle 11g | Oracle 12c | Miscellaneo us | PL/SQL | SQL | Oracle RAC | Oracle Apps | Linux
Ho me Artic le s 11g He re Like 0 Twe e t 0 1 Searc h

Trigger Enhancements in Oracle Database 11g Release 1


Executio n Order o f Trig g ers Co mpo und Trig g ers Enable and Disable Trig g ers

Execution Order of Triggers


Oracle allo ws mo re than o ne trig g er to be created fo r the same timing po int, but it has never g uaranteed the executio n o rder o f tho se trig g ers. The Oracle 11g trig g er syntax no w includes the FOLLOWS clause to g uarantee executio n o rder fo r trig g ers defined with the same timing po int. The fo llo wing example creates a table with two trig g ers fo r the same timing po int. CREATE TABLE trigger_follows_test ( id NUMBER, description VARCHAR2(50) ); CREATE OR REPLACE TRIGGER trigger_follows_test_trg_1 BEFORE INSERT ON trigger_follows_test FOR EACH ROW BEGIN DBMS_OUTPUT.put_line('TRIGGER_FOLLOWS_TEST_TRG_1 - Executed'); END; / CREATE OR REPLACE TRIGGER trigger_follows_test_trg_2 BEFORE INSERT ON trigger_follows_test FOR EACH ROW BEGIN DBMS_OUTPUT.put_line('TRIGGER_FOLLOWS_TEST_TRG_2 - Executed'); END;
PDFmyURL.com

/ If we insert into the test table, there is no g uarantee o f the executio n o rder. SQL> SET SERVEROUTPUT ON SQL> INSERT INTO trigger_follows_test VALUES (1, 'ONE'); TRIGGER_FOLLOWS_TEST_TRG_1 - Executed TRIGGER_FOLLOWS_TEST_TRG_2 - Executed 1 row created. SQL> We can specify that the TRIGGER_FOLLOWS_TEST_TRG_2 trig g er sho uld be executed befo re the TRIGGER_FOLLOWS_TEST_TRG_1 trig g er by recreating the TRIGGER_FOLLOWS_TEST_TRG_1 trig g er using the FOLLOWS clause. CREATE OR REPLACE TRIGGER trigger_follows_test_trg_1 BEFORE INSERT ON trigger_follows_test FOR EACH ROW FOLLOWS trigger_follows_test_trg_2 BEGIN DBMS_OUTPUT.put_line('TRIGGER_FOLLOWS_TEST_TRG_1 - Executed'); END; / No w the TRIGGER_FOLLOWS_TEST_TRG_1 trig g er always fo llo ws the TRIGGER_FOLLOWS_TEST_TRG_2 trig g er. SQL> SET SERVEROUTPUT ON SQL> INSERT INTO trigger_follows_test VALUES (2, 'TWO'); TRIGGER_FOLLOWS_TEST_TRG_2 - Executed TRIGGER_FOLLOWS_TEST_TRG_1 - Executed 1 row created. SQL> Do n't fo rg et to clean up the test table. DROP TABLE trigger_follows_test;

PDFmyURL.com

Compound Triggers
A co mpo und trig g er allo ws co de fo r o ne o r mo re timing po ints fo r a specific o bject to be co mbined into a sing le trig g er. The individual timing po ints can share a sing le g lo bal declaratio n sectio n, who se state is maintained fo r the lifetime o f the statement. Once a statement ends, due to successful co mpletio n o r an erro r, the trig g er state is cleaned up. In previo us releases this type o f functio nality was o nly po ssible by defining multiple trig g ers who se co de and g lo bal variables were defined in a separate packag e, as sho wn in the Mutating Table Exceptio ns article, but the co mpo und trig g er allo ws fo r a much tidier so lutio n. The trig g ering actio ns are defined in the same way as any o ther DML trig g er, with the additio n o f the COMPOUND TRIGGER clause. The main bo dy o f the trig g er is made up o f an o ptio nal g lo bal declaratio n sectio n and o ne o r mo re timing po int sectio ns, each o f which may co ntain a lo cal declaratio n sectio n who se state is no t maintained. CREATE OR REPLACE TRIGGER <trigger-name> FOR <trigger-action> ON <table-name> COMPOUND TRIGGER -- Global declaration. g_global_variable VARCHAR2(10); BEFORE STATEMENT IS BEGIN NULL; -- Do something here. END BEFORE STATEMENT; BEFORE EACH ROW IS BEGIN NULL; -- Do something here. END BEFORE EACH ROW; AFTER EACH ROW IS BEGIN NULL; -- Do something here. END AFTER EACH ROW; AFTER STATEMENT IS BEGIN NULL; -- Do something here. END AFTER STATEMENT; END <trigger-name>; / The fo llo wing co de creates a test table and a co mpo und trig g er that fires fo r each timing po int asso ciated with insert, update and delete statements. The trig g ering actio ns are lo g g ed in a PL/SQL table defined in the g lo bal declaratio n sectio n. The final timing po int fo r each statement prints o ut the co ntent o f the PL/SQL table to sho w that the variable state has been maintained thro ug ho ut the lifetime o f the statement. CREATE TABLE compound_trigger_test (
PDFmyURL.com

CREATE TABLE compound_trigger_test ( id NUMBER, description VARCHAR2(50) ); CREATE OR REPLACE TRIGGER compound_trigger_test_trg FOR INSERT OR UPDATE OR DELETE ON compound_trigger_test COMPOUND TRIGGER -- Global declaration. TYPE t_tab IS TABLE OF VARCHAR2(50); l_tab t_tab := t_tab(); BEFORE STATEMENT IS BEGIN l_tab.extend; CASE WHEN INSERTING THEN l_tab(l_tab.last) := 'BEFORE STATEMENT - INSERT'; WHEN UPDATING THEN l_tab(l_tab.last) := 'BEFORE STATEMENT - UPDATE'; WHEN DELETING THEN l_tab(l_tab.last) := 'BEFORE STATEMENT - DELETE'; END CASE; END BEFORE STATEMENT; BEFORE EACH ROW IS BEGIN l_tab.extend; CASE WHEN INSERTING THEN l_tab(l_tab.last) := 'BEFORE EACH ROW - INSERT (new.id=' || :new.id || ')'; WHEN UPDATING THEN l_tab(l_tab.last) := 'BEFORE EACH ROW - UPDATE (new.id=' || :new.id || ' old.id=' || :old.id || ')'; WHEN DELETING THEN l_tab(l_tab.last) := 'BEFORE EACH ROW - DELETE (old.id=' || :old.id || ')'; END CASE; END BEFORE EACH ROW; AFTER EACH ROW IS BEGIN l_tab.extend; CASE WHEN INSERTING THEN l_tab(l_tab.last) := 'AFTER EACH ROW - INSERT (new.id=' || :new.id || ')'; WHEN UPDATING THEN l_tab(l_tab.last) := 'AFTER EACH ROW - UPDATE (new.id=' || :new.id || ' old.id=' || :old.id || ')';
PDFmyURL.com

WHEN DELETING THEN l_tab(l_tab.last) := 'AFTER EACH ROW - DELETE (old.id=' || :old.id || ')'; END CASE; END AFTER EACH ROW; AFTER STATEMENT IS BEGIN l_tab.extend; CASE WHEN INSERTING THEN l_tab(l_tab.last) := 'AFTER STATEMENT - INSERT'; WHEN UPDATING THEN l_tab(l_tab.last) := 'AFTER STATEMENT - UPDATE'; WHEN DELETING THEN l_tab(l_tab.last) := 'AFTER STATEMENT - DELETE'; END CASE; FOR i IN l_tab.first .. l_tab.last LOOP DBMS_OUTPUT.put_line(l_tab(i)); END LOOP; l_tab.delete; END AFTER STATEMENT; END compound_trigger_test_trg; / By issuing several insert, update and delete statements ag ainst the test table we can see that the co mpo und trig g er is wo rking as expected. SQL> SET SERVEROUTPUT ON SQL> INSERT INTO compound_trigger_test VALUES (1, 'ONE'); BEFORE STATEMENT - INSERT BEFORE EACH ROW - INSERT (new.id=1) AFTER EACH ROW - INSERT (new.id=1) AFTER STATEMENT - INSERT 1 row created. SQL> INSERT INTO compound_trigger_test VALUES (2, 'TWO'); BEFORE STATEMENT - INSERT BEFORE EACH ROW - INSERT (new.id=2) AFTER EACH ROW - INSERT (new.id=2) AFTER STATEMENT - INSERT 1 row created.
PDFmyURL.com

SQL> UPDATE compound_trigger_test SET id = id; BEFORE STATEMENT - UPDATE BEFORE EACH ROW - UPDATE (new.id=2 old.id=2) AFTER EACH ROW - UPDATE (new.id=2 old.id=2) BEFORE EACH ROW - UPDATE (new.id=1 old.id=1) AFTER EACH ROW - UPDATE (new.id=1 old.id=1) AFTER STATEMENT - UPDATE 2 rows updated. SQL> DELETE FROM compound_trigger_test; BEFORE STATEMENT - DELETE BEFORE EACH ROW - DELETE (old.id=2) AFTER EACH ROW - DELETE (old.id=2) BEFORE EACH ROW - DELETE (old.id=1) AFTER EACH ROW - DELETE (old.id=1) AFTER STATEMENT - DELETE 2 rows deleted. SQL> Do n't fo rg et to clean up the test table. DROP TABLE compound_trigger_test; Fo r a mo re practical use o f co mpo und trig g ers, we can take the example quo ted in the Mutating Table Exceptio ns article and replace the two trig g ers and the packag e with a sing le co mpo und trig g er, as sho wn belo w. CREATE OR REPLACE TRIGGER tab1_compound_trigger FOR INSERT OR UPDATE ON tab1 COMPOUND TRIGGER TYPE t_change_tab IS TABLE OF tab1_audit%ROWTYPE; g_change_tab t_change_tab := t_change_tab(); AFTER EACH ROW IS BEGIN g_change_tab.extend; g_change_tab(g_change_tab.last).id IF INSERTING THEN g_change_tab(g_change_tab.last).action ELSE g_change_tab(g_change_tab.last).action

:= tab1_audit_seq.NEXTVAL; := 'INSERT'; := 'UPDATE';


PDFmyURL.com

END IF; g_change_tab(g_change_tab.last).tab1_id := :new.id; g_change_tab(g_change_tab.last).created_time := SYSTIMESTAMP; END AFTER EACH ROW; AFTER STATEMENT IS l_count NUMBER(10); BEGIN FOR i IN g_change_tab.first .. g_change_tab.last LOOP SELECT COUNT(*) INTO g_change_tab(i).record_count FROM tab1; END LOOP; FORALL i IN g_change_tab.first .. g_change_tab.last INSERT INTO tab1_audit VALUES g_change_tab(i); g_change_tab.delete; END AFTER STATEMENT; END tab1_compound_trigger; / Fro m a timing po int perspective, the Co mpo und Trig g er Restrictio ns fo llo w very clo sely with tho se o f individual statement and ro w level trig g ers. The main po int o f interest here is the co ntro l o f executio n o rder. If multiple co mpo und trig g ers are defined fo r the same o bject, their o rder o f executio n can be co ntro lled using the FOLLOWS clause, but this canno t be used to co ntro l executio n o rder when bo th co mpo und and reg ular DML trig g ers are defined ag ainst a sing le o bject. In such situatio ns it is better to stick with all DML trig g ers, o r all co mpo und trig g ers.

Enable and Disable Triggers


It has been po ssible to enable and disable trig g ers fo r so me time using the ALTER TRIGGER and ALTER TABLE co mmands. ALTER ALTER ALTER ALTER TRIGGER <trigger-name> DISABLE; TRIGGER <trigger-name> ENABLE; TABLE <table-name> DISABLE ALL TRIGGERS; TABLE <table-name> ENABLE ALL TRIGGERS;

Prio r to 11g , it was o nly po ssible to create trig g ers in the enabled state, then subsequently disable them. No w they can be explicitly enabled o r disabled at creatio n time, with the enabled state as the default. CREATE TABLE trigger_control_test ( id NUMBER, description VARCHAR2(50) );
PDFmyURL.com

CREATE OR REPLACE TRIGGER trigger_control_test_trg BEFORE INSERT ON trigger_control_test FOR EACH ROW ENABLE BEGIN DBMS_OUTPUT.put_line('TRIGGER_CONTROL_TEST_TRG - Executed'); END; / SQL> SET SERVEROUTPUT ON SQL> INSERT INTO trigger_control_test VALUES (1, 'ONE'); TRIGGER_CONTROL_TEST_TRG - Executed 1 row created. SQL> CREATE OR REPLACE TRIGGER trigger_control_test_trg BEFORE INSERT ON trigger_control_test FOR EACH ROW DISABLE BEGIN DBMS_OUTPUT.put_line('TRIGGER_CONTROL_TEST_TRG - Executed'); END; / SQL> INSERT INTO trigger_control_test VALUES (2, 'TWO'); 1 row created. SQL> Do n't fo rg et to clean up the test table. DROP TABLE trigger_control_test; Fo r mo re info rmatio n see: What's New in PL/SQL? - Oracle Database PL/SQL Lang uag e Reference 11g Release 1 (11.1) CREATE TRIGGER Co mpo und Trig g ers Ho pe this helps. Reg ards Tim... Back to the To p.
PDFmyURL.com

7 co mments, read/add them...


Like 0 Twe e t 0 1

Ho me | Articles | Scripts | Fo rums | Blo g | Certificatio n | Misc | Search | Abo ut


Co pyrig ht & Disc la ime r HTML CSS

PDFmyURL.com