Database Triggers Overview
An introduction to database triggers in Oracle.
oracle miscconfigurationintermediate
by OracleDba
16 views
An introduction to database triggers in Oracle.
1234567891011121314151617181920212223242526272829303132333435
CREATE [OR REPLACE] TRIGGER schema.trigger-name
{BEFORE | AFTER} dml-event ON table-name
[FOR EACH ROW]
[DECLARE ...]
BEGIN
-- Your PL/SQL code goes here.
[EXCEPTION ...]
END;
/
INSERT
UPDATE
UPDATE OF column-name[, column-name ...]
DELETE
INSERT OR UPDATE OR DELETE
CREATE OR REPLACE TRIGGER my_test_trg
BEFORE INSERT OR UPDATE OR DELETE ON my_table
FOR EACH ROW
BEGIN
-- Flags are booleans and can be used in any branching construct.
CASE
WHEN INSERTING THEN
-- Include any code specific for when the trigger is fired from an INSERT.
-- Also fired for INSERT as part of a MERGE.
WHEN UPDATING THEN
-- Include any code specific for when the trigger is fired from an UPDATE.
-- Also fired for UPDATE as part of a MERGE.
WHEN DELETING THEN
-- Include any code specific for when the trigger is fired from a DELETE.
-- Does not fire for DELETE clause of a MERGE.
END CASE;
END;
/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
DROP TABLE trigger_test;
CREATE TABLE trigger_test (
id NUMBER NOT NULL,
description VARCHAR2(50) NOT NULL
);
CREATE OR REPLACE PACKAGE trigger_test_api AS
TYPE t_tab IS TABLE OF VARCHAR2(50);
g_tab t_tab := t_tab();
END trigger_test_api;
/
-- BEFORE STATEMENT
CREATE OR REPLACE TRIGGER trigger_test_bs_trg
BEFORE INSERT OR UPDATE OR DELETE ON trigger_test
BEGIN
trigger_test_api.g_tab.extend;
CASE
WHEN INSERTING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'BEFORE STATEMENT - INSERT';
WHEN UPDATING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'BEFORE STATEMENT - UPDATE';
WHEN DELETING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'BEFORE STATEMENT - DELETE';
END CASE;
END;
/
-- BEFORE ROW
CREATE OR REPLACE TRIGGER trigger_test_br_trg
BEFORE INSERT OR UPDATE OR DELETE ON trigger_test
FOR EACH ROW
BEGIN
trigger_test_api.g_tab.extend;
CASE
WHEN INSERTING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'BEFORE EACH ROW - INSERT (new.id=' || :new.id || ')';
WHEN UPDATING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'BEFORE EACH ROW - UPDATE (new.id=' || :new.id || ' old.id=' || :old.id || ')';
WHEN DELETING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'BEFORE EACH ROW - DELETE (old.id=' || :old.id || ')';
END CASE;
END trigger_test_br_trg;
/
-- AFTER ROW
CREATE OR REPLACE TRIGGER trigger_test_ar_trg
AFTER INSERT OR UPDATE OR DELETE ON trigger_test
FOR EACH ROW
BEGIN
trigger_test_api.g_tab.extend;
CASE
WHEN INSERTING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER EACH ROW - INSERT (new.id=' || :new.id || ')';
WHEN UPDATING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER EACH ROW - UPDATE (new.id=' || :new.id || ' old.id=' || :old.id || ')';
WHEN DELETING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER EACH ROW - DELETE (old.id=' || :old.id || ')';
END CASE;
END trigger_test_ar_trg;
/
-- AFTER STATEMENT
CREATE OR REPLACE TRIGGER trigger_test_as_trg
AFTER INSERT OR UPDATE OR DELETE ON trigger_test
BEGIN
trigger_test_api.g_tab.extend;
CASE
WHEN INSERTING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER STATEMENT - INSERT';
WHEN UPDATING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER STATEMENT - UPDATE';
WHEN DELETING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER STATEMENT - DELETE';
END CASE;
FOR i IN trigger_test_api.g_tab.first .. trigger_test_api.g_tab.last LOOP
DBMS_OUTPUT.put_line(trigger_test_api.g_tab(i));
END LOOP;
trigger_test_api.g_tab.delete;
END trigger_test_as_trg;
/
COLUMN object_name FORMAT A20
SELECT object_name, object_type, status FROM user_objects;
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
TRIGGER_TEST_API PACKAGE VALID
TRIGGER_TEST TABLE VALID
TRIGGER_TEST_BS_TRG TRIGGER VALID
TRIGGER_TEST_BR_TRG TRIGGER VALID
TRIGGER_TEST_AR_TRG TRIGGER VALID
TRIGGER_TEST_AS_TRG TRIGGER VALID
6 rows selected.
SQL>
SQL> SET SERVEROUTPUT ON
SQL> INSERT INTO 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 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.
SQL> UPDATE 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 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> ROLLBACK;
Rollback complete.
SQL>
SET SERVEROUTPUT ON
INSERT INTO trigger_test
SELECT level, 'Description for ' || level
FROM dual
CONNECT BY level <= 5;
BEFORE STATEMENT - INSERT
BEFORE EACH ROW - INSERT (new.id=1)
AFTER EACH ROW - INSERT (new.id=1)
BEFORE EACH ROW - INSERT (new.id=2)
AFTER EACH ROW - INSERT (new.id=2)
BEFORE EACH ROW - INSERT (new.id=3)
AFTER EACH ROW - INSERT (new.id=3)
BEFORE EACH ROW - INSERT (new.id=4)
AFTER EACH ROW - INSERT (new.id=4)
BEFORE EACH ROW - INSERT (new.id=5)
AFTER EACH ROW - INSERT (new.id=5)
AFTER STATEMENT - INSERT
5 rows created.
SQL> ROLLBACK;
Rollback complete.
SQL>
SET SERVEROUTPUT ON
INSERT INTO trigger_test
SELECT level, 'Description for ' || level
FROM dual
CONNECT BY level <= 5;
BEFORE STATEMENT - INSERT
BEFORE EACH ROW - INSERT (new.id=1)
BEFORE EACH ROW - INSERT (new.id=2)
BEFORE EACH ROW - INSERT (new.id=3)
BEFORE EACH ROW - INSERT (new.id=4)
BEFORE EACH ROW - INSERT (new.id=5)
AFTER EACH ROW - INSERT (new.id=1)
AFTER EACH ROW - INSERT (new.id=2)
AFTER EACH ROW - INSERT (new.id=3)
AFTER EACH ROW - INSERT (new.id=4)
AFTER EACH ROW - INSERT (new.id=5)
AFTER STATEMENT - INSERT
5 rows created.
SQL> ROLLBACK;
Rollback complete.
SQL>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
SET SERVEROUTPUT ON
DECLARE
TYPE t_trigger_test_tab IS TABLE OF trigger_test%ROWTYPE;
l_tt_tab t_trigger_test_tab := t_trigger_test_tab();
BEGIN
FOR i IN 1 .. 5 LOOP
l_tt_tab.extend;
l_tt_tab(l_tt_tab.last).id := i;
l_tt_tab(l_tt_tab.last).description := 'Description for ' || i;
END LOOP;
DBMS_OUTPUT.put_line('*** FORALL - INSERT ***');
-- APPEND_VALUES hint is an 11gR2 feature, but doesn't affect timing points.
FORALL i IN l_tt_tab.first .. l_tt_tab.last
INSERT /*+ APPEND_VALUES */ INTO trigger_test VALUES l_tt_tab(i);
DBMS_OUTPUT.put_line('*** FORALL - UPDATE ***');
-- Referencing collection columns in FORALL is only supported in 11g.
FORALL i IN l_tt_tab.first .. l_tt_tab.last
UPDATE trigger_test SET description = l_tt_tab(i).description WHERE id = l_tt_tab(i).id;
DBMS_OUTPUT.put_line('*** FORALL - DELETE ***');
-- Referencing collection columns in FORALL is only supported in 11g.
FORALL i IN l_tt_tab.first .. l_tt_tab.last
DELETE FROM trigger_test WHERE id = l_tt_tab(i).id;
ROLLBACK;
END;
/
*** FORALL - INSERT ***
BEFORE STATEMENT - INSERT
BEFORE EACH ROW - INSERT (new.id=1)
AFTER EACH ROW - INSERT (new.id=1)
BEFORE EACH ROW - INSERT (new.id=2)
AFTER EACH ROW - INSERT (new.id=2)
BEFORE EACH ROW - INSERT (new.id=3)
AFTER EACH ROW - INSERT (new.id=3)
BEFORE EACH ROW - INSERT (new.id=4)
AFTER EACH ROW - INSERT (new.id=4)
BEFORE EACH ROW - INSERT (new.id=5)
AFTER EACH ROW - INSERT (new.id=5)
AFTER STATEMENT - INSERT
*** FORALL - UPDATE ***
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=1 old.id=1)
AFTER EACH ROW - UPDATE (new.id=1 old.id=1)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=2 old.id=2)
AFTER EACH ROW - UPDATE (new.id=2 old.id=2)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=3 old.id=3)
AFTER EACH ROW - UPDATE (new.id=3 old.id=3)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=4 old.id=4)
AFTER EACH ROW - UPDATE (new.id=4 old.id=4)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=5 old.id=5)
AFTER EACH ROW - UPDATE (new.id=5 old.id=5)
AFTER STATEMENT - UPDATE
*** FORALL - DELETE ***
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=1)
AFTER EACH ROW - DELETE (old.id=1)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=2)
AFTER EACH ROW - DELETE (old.id=2)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=3)
AFTER EACH ROW - DELETE (old.id=3)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=4)
AFTER EACH ROW - DELETE (old.id=4)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=5)
AFTER EACH ROW - DELETE (old.id=5)
AFTER STATEMENT - DELETE
PL/SQL procedure successfully completed.
SQL>
*** FORALL - INSERT ***
BEFORE STATEMENT - INSERT
BEFORE EACH ROW - INSERT (new.id=1)
BEFORE EACH ROW - INSERT (new.id=2)
BEFORE EACH ROW - INSERT (new.id=3)
BEFORE EACH ROW - INSERT (new.id=4)
BEFORE EACH ROW - INSERT (new.id=5)
AFTER EACH ROW - INSERT (new.id=1)
AFTER EACH ROW - INSERT (new.id=2)
AFTER EACH ROW - INSERT (new.id=3)
AFTER EACH ROW - INSERT (new.id=4)
AFTER EACH ROW - INSERT (new.id=5)
AFTER STATEMENT - INSERT
*** FORALL - UPDATE ***
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=1 old.id=1)
AFTER EACH ROW - UPDATE (new.id=1 old.id=1)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=2 old.id=2)
AFTER EACH ROW - UPDATE (new.id=2 old.id=2)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=3 old.id=3)
AFTER EACH ROW - UPDATE (new.id=3 old.id=3)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=4 old.id=4)
AFTER EACH ROW - UPDATE (new.id=4 old.id=4)
AFTER STATEMENT - UPDATE
BEFORE STATEMENT - UPDATE
BEFORE EACH ROW - UPDATE (new.id=5 old.id=5)
AFTER EACH ROW - UPDATE (new.id=5 old.id=5)
AFTER STATEMENT - UPDATE
*** FORALL - DELETE ***
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=1)
AFTER EACH ROW - DELETE (old.id=1)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=2)
AFTER EACH ROW - DELETE (old.id=2)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=3)
AFTER EACH ROW - DELETE (old.id=3)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=4)
AFTER EACH ROW - DELETE (old.id=4)
AFTER STATEMENT - DELETE
BEFORE STATEMENT - DELETE
BEFORE EACH ROW - DELETE (old.id=5)
AFTER EACH ROW - DELETE (old.id=5)
AFTER STATEMENT - DELETE
PL/SQL procedure successfully completed.
SQL>12345678910111213141516171819202122232425262728293031323334353637383940414243
CREATE OR REPLACE TRIGGER trigger_test_ar_trg
AFTER INSERT OR UPDATE OR DELETE ON trigger_test
FOR EACH ROW
BEGIN
trigger_test_api.g_tab.extend;
CASE
WHEN INSERTING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER EACH ROW - INSERT (new.id=' || :new.id || ')';
WHEN UPDATING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER EACH ROW - UPDATE (new.id=' || :new.id || ' old.id=' || :old.id || ')';
WHEN DELETING THEN
trigger_test_api.g_tab(trigger_test_api.g_tab.last) := 'AFTER EACH ROW - DELETE (old.id=' || :old.id || ')';
END CASE;
RAISE_APPLICATION_ERROR(-20000, 'Forcing an error.');
END trigger_test_ar_trg;
/
SET SERVEROUTPUT ON
INSERT INTO trigger_test VALUES (1, 'ONE');
*
ERROR at line 1:
ORA-20000: Forcing an error.
ORA-06512: at "TEST.TRIGGER_TEST_AR_TRG", line 11
ORA-04088: error during execution of trigger 'TEST.TRIGGER_TEST_AR_TRG'
SQL>
BEGIN
FOR i IN trigger_test_api.g_tab.first .. trigger_test_api.g_tab.last LOOP
DBMS_OUTPUT.put_line(trigger_test_api.g_tab(i));
END LOOP;
trigger_test_api.g_tab.delete;
END;
/
BEFORE STATEMENT - INSERT
BEFORE EACH ROW - INSERT (new.id=1)
AFTER EACH ROW - INSERT (new.id=1)
PL/SQL procedure successfully completed.
SQL>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
-- Clean up.
DROP TABLE t1 PURGE;
DROP TABLE t2 PURGE;
DROP SEQUENCE t1_seq;
DROP PROCEDURE p1;
-- Create object.
CREATE TABLE t1 (
id NUMBER
);
CREATE SEQUENCE t1_seq;
CREATE OR REPLACE PROCEDURE p1 (p_commit IN BOOLEAN DEFAULT TRUE) AS
BEGIN
INSERT INTO t1 (id) VALUES (t1_seq.nextval);
IF p_commit THEN
COMMIT;
END IF;
END;
/
-- Create some data using procedure.
BEGIN
p1(p_commit => FALSE);
p1;
END;
/
-- Check the contents of the test table.
SELECT * FROM t1;
ID
----------
1
2
2 rows selected.
SQL>
SQL> @code_dep test p1
REFERENCED_TYPE REFERENCED_OWNER REFERENCED_NAME REFERENCED_LINK_NAME
-------------------- -------------------- ---------------------------------------- --------------------
PACKAGE SYS STANDARD
SYS SYS_STUB_FOR_PURITY_ANALYSIS
SEQUENCE TEST T1_SEQ
TABLE TEST T1
4 rows selected.
SQL>
-- Create new objects
CREATE TABLE t2 (
id NUMBER
);
CREATE OR REPLACE TRIGGER t1_after_insert_trg
AFTER INSERT ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (id) VALUES (:new.id);
END;
/
-- Run procedure again
BEGIN
p1;
END;
/
-- Check contents of tables.
SELECT * FROM t1;
ID
----------
1
2
3
3 rows selected.
SQL>
SELECT * FROM t2;
ID
----------
3
1 row selected.
SQL>
@code_dep test p1
REFERENCED_TYPE REFERENCED_OWNER REFERENCED_NAME REFERENCED_LINK_NAME
-------------------- -------------------- ---------------------------------------- --------------------
PACKAGE SYS STANDARD
SYS SYS_STUB_FOR_PURITY_ANALYSIS
SEQUENCE TEST T1_SEQ
TABLE TEST T1
4 rows selected.
SQL>12345678910111213141516
CREATE [OR REPLACE] TRIGGER trigger-name
{ BEFORE | AFTER } event [OR event]...
ON { [schema.] SCHEMA | DATABASE }
[DECLARE ...]
BEGIN
-- Your PL/SQL code goes here.
[EXCEPTION ...]
END;
/
CREATE OR REPLACE TRIGGER app_user.after_logon_trg
AFTER LOGON ON app_user.SCHEMA
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION SET current_schema=SCHEMA_OWNER';
END;
/12345
ALTER TRIGGER trigger-name DISABLE;
ALTER TRIGGER trigger-name ENABLE;
ALTER TABLE table-name DISABLE ALL TRIGGERS;
ALTER TABLE table-name ENABLE ALL TRIGGERS;Please to add comments
No comments yet. Be the first to comment!