A trigger törzse állhat egyetlen CALL utasításból, amely egy tárolt eljárást hív meg. Ez az eljárás lehet PL/SQL eljárás, de lehet egy C vagy Java nyelven megírt eljárás is.
Másik lehetőség, hogy a trigger törzse egy PL/SQL blokk. Minden, amit a blokkról írtunk, itt is igaz, de van néhány korlátozás. A trigger törzsét alkotó blokkban nem lehetnek tranzakcióvezérlő utasítások (COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION). Természetesen a törzsből hívott alprogramok sem tartalmazhatják ezeket az utasításokat. A PL/SQL fordító megengedi ezeket, hibát csak a trigger futása közben okoznak.
Olyan triggerben, amelynek törzse autonóm tranzakciót tartalmaz, használhatók a tranzakcióvezérlő utasítások.
Autonóm tranzakciót tartalmazó kölcsönösen rekurzív triggerek használata az erőforrások zárolása miatt holtpontot eredményezhet.
1. példa
/* Holtpont az AUTONOMOUS_TRANSACTION miatt rekurzív triggerekben. */
CREATE TABLE tab_1 (a NUMBER);
INSERT INTO tab_1 VALUES(1);
CREATE TABLE tab_2 (a NUMBER);
INSERT INTO tab_2 VALUES(1);
CREATE OR REPLACE TRIGGER tr_tab1
AFTER DELETE ON tab_1
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
DELETE FROM tab_2;
END tr_tab1;
/
CREATE OR REPLACE TRIGGER tr_tab2
AFTER DELETE ON tab_2
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
DELETE FROM tab_1;
END tr_tab2;
/
DELETE FROM tab_1;
/* Eredmény:
Hiba a(z) 1. sorban:
DELETE FROM tab_1
*
ORA-00060: erőforrásra várakozás közben holtpont jött létre
ORA-06512: a(z) "PLSQL.TR_TAB2", helyen a(z) 4. sornál
ORA-04088: hiba a(z) 'PLSQL.TR_TAB2' trigger futása közben
ORA-06512: a(z) "PLSQL.TR_TAB1", helyen a(z) 4. sornál
ORA-04088: hiba a(z) 'PLSQL.TR_TAB1' trigger futása közben
*/
A DML triggerek törzsében használható három paraméter nélküli logikai függvény, amelyek a triggert aktivizáló utasításról adnak információt (miután egy triggert több DML utasítás is aktivizálhat). Ezek a függvények az INSERTING, DELETING, UPDATING függvények, amelyek rendre akkor térnek vissza igaz értékkel, ha az aktivizáló utasítás az INSERT, DELETE, UPDATE volt.
2. példa
/* A szükséges táblák és az eljárás az előző példában voltak definiálva. */
CREATE OR REPLACE TRIGGER tr_utasitas_before
BEFORE INSERT OR UPDATE OR DELETE ON tabla
BEGIN
tabla_insert('UTASITAS BEFORE ' || CASE
WHEN INSERTING THEN 'INSERT'
WHEN UPDATING THEN 'UPDATE'
WHEN DELETING THEN 'DELETE'
END);
END tr_utasitas_before;
/
CREATE OR REPLACE TRIGGER tr_utasitas_after
AFTER INSERT OR UPDATE OR DELETE ON tabla
BEGIN
tabla_insert('UTASITAS AFTER ' || CASE
WHEN INSERTING THEN 'INSERT'
WHEN UPDATING THEN 'UPDATE'
WHEN DELETING THEN 'DELETE'
END);
END tr_utasitas_after;
/
show errors;
CREATE OR REPLACE TRIGGER tr_sor_before
BEFORE INSERT OR UPDATE OR DELETE ON tabla
FOR EACH ROW
BEGIN
tabla_insert('sor before ' || :OLD.a || ', ' || :NEW.a
|| ' ' || CASE
WHEN INSERTING THEN 'insert'
WHEN UPDATING THEN 'update'
WHEN DELETING THEN 'delete'
END);
END tr_sor_before;
/
show errors;
CREATE OR REPLACE TRIGGER tr_sor_after
AFTER INSERT OR UPDATE OR DELETE ON tabla
FOR EACH ROW
BEGIN
tabla_insert('sor after ' || :OLD.a || ', ' || :NEW.a
|| ' ' || CASE
WHEN INSERTING THEN 'insert'
WHEN UPDATING THEN 'update'
WHEN DELETING THEN 'delete'
END);
END tr_sor_after;
/
DELETE FROM tabla;
DELETE FROM tabla_log;
-- Biztosan létezik 2 tábla a sémában. */
INSERT INTO tabla
(SELECT ROWNUM FROM tab WHERE ROWNUM <= 2);
UPDATE tabla SET a = a+10;
DELETE FROM tabla;
SELECT * FROM tabla_log;
/*
S
------------------------------
UTASITAS BEFORE INSERT
sor before , 1 insert
sor after , 1 insert
sor before , 2 insert
sor after , 2 insert
UTASITAS AFTER INSERT
UTASITAS BEFORE UPDATE
sor before 1, 11 update
sor after 1, 11 update
sor before 2, 12 update
sor after 2, 12 update
UTASITAS AFTER UPDATE
UTASITAS BEFORE DELETE
sor before 11, delete
sor after 11, delete
sor before 12, delete
sor after 12, delete
UTASITAS AFTER DELETE
*/
Rendszertrigger létrhozásához ADMINISTER DATABASE TRIGGER rendszerjogosultság szükséges.
A rendszertriggerek törzsében az ún. eseményattribútum függvények használhatók, melyek a bekövetkezett rendszer- és felhasználói események jellemzőit adják meg. Ezek a függvények ugyan bármely PL/SQL blokkból meghívhatók, de valós eredményt csak egy trigger törzsében szolgáltatnak. Ezek a függvények a SYS tulajdonában lévő függvények, nyilvános szinonimáik ora_ prefixszel kezdődnek. A szinonimák ismertetését a 13.1. táblázat tartalmazza.
13.1. táblázat - Eseményattribútum függvények
Szinonima |
Típus |
Leírás |
Példa |
ora_client_ip_address |
VARCHAR2 |
TCP/IP protokoll esetén megadja a kliens IP-címét LOGON esemény bekövetkeztekor. |
IF ora_sysevent = 'LOGON' THEN cim := ora_client_ip_address; END IF; |
ora_database_name |
VARCHAR2(50) |
Az adatbázis nevét adja meg. |
DECLARE db_nev VARCHAR2(50); BEGIN db_nev := ora_database_name; END; |
ora_des_encrypted_password |
VARCHAR2 |
Az éppen létrehozás vagy módosítás alatt álló felhasználó jelszava DES titkosítással. |
IF ora_dict_obj_type = 'USER' THEN INSERT INTO esemenyek VALUES (ora_des_encrypted_password); END IF; |
ora_dict_obj_name |
VARCHAR2(30) |
Azon adatszótárbeli objektum neve, amelyen a DDL művelet végrehajtódik. |
INSERT INTO esemenyek VALUES ('Változtatott objektum: ' || ora_dict_obj_name); |
ora_dict_obj_name_list (nev_lista OUT ora_name_list_t) |
BINARY_INTEGER |
Az éppen módosítás alatt álló objektumok számát és neveinek listáját határozza meg. |
IF ora_sysevent = 'ASSOCIATE STATISTICS' THEN valt_obj_szama := ora_dict_obj_name_list (nev_lista); END IF; |
ora_dict_obj_owner |
VARCHAR2(30) |
Azon adatszótárbeli objektum tulajdonosa, amelyen a DDL művelet végrehajtódik. |
INSERT INTO esemenyek VALUES ('Objektum tulajdonosa: ' || ora_dict_obj_owner); |
ora_dict_obj_owner_list (tulaj_lista OUT ora_name_list_t) |
BINARY_INTEGER |
Az éppen módosítás alatt álló objektumok számát és tulajdonosaik nevének listáját határozza meg. |
IF ora_sysevent = 'ASSOCIATE STATISTICS' THEN valt_obj_szama := ora_dict_obj_owner_list( tulaj_lista); END IF; |
ora_dict_obj_type |
VARCHAR(20) |
Azon adatszótárbeli objektum típusa, amelyen a DDL művelet végrehajtódik. |
INSERT INTO esemenyek VALUES ('Objektum típusa: ' || ora_dict_obj_type); |
ora_grantee( felh_lista OUT ora_name_list_t) |
BINARY_INTEGER |
A feljogosítottak számát és listáját határozza meg. |
IF ora_sysevent = 'GRANT' THEN felh_szama := ora_grantee(felh_lista); END IF; |
ora_instance_num |
NUMBER |
Az adatbázispéldány számát adja meg. |
IF ora_instance_num = 1 THEN INSERT INTO esemenyek VALUES ('1'); END IF; |
ora_is_alter_column( oszlop_nev IN VARCHAR2) |
BOOLEAN |
Igazzal tér vissza, ha a megadott oszlop megváltozott. |
IF ora_sysevent = 'ALTER' AND ora_dict_obj_type = 'TABLE' THEN oszlop_valtozott := ora_is_alter_column('FOO'); END IF; |
ora_is_creating_nested_table |
BOOLEAN |
Igazzal tér vissza, ha beágyazott tábla jött létre. |
IF ora_sysevent = 'CREATE' AND ora_dict_obj_type = 'TABLE' AND ora_is_creating_nested_table THEN INSERT INTO esemenyek VALUES ('Egy beágyazott tábla jött létre.'); END IF; |
ora_is_drop_column( oszlop_nev IN VARCHAR2) |
BOOLEAN |
Igazzal tér vissza, ha a megadott oszlop törlődött. |
IF ora_sysevent = 'ALTER' AND ora_dict_obj_type = 'TABLE' THEN drop_column := ora_is_drop_column('FOO'); END IF; |
ora_is_servererror( hiba_szam IN NUMBER) |
BOOLEAN |
Igazzal tér vissza, ha a megadott hiba a hibaveremben van. |
IF ora_is_servererror(hiba_szam) THEN INSERT INTO esemenyek VALUES ('Szerverhiba!!'); END IF; |
ora_login_user |
VARCHAR2(30) |
A bejelentkezett felhasználó nevét adja meg. |
SELECT ora_login_user FROM dual; |
ora_partition_pos |
BINARY_INTEGER |
Egy CREATE TABLE-re vonatkozó INSTEAD OF triggerben megadja, hogy a táblát létrehozó utasítás mely pozícióján lehet PARTITION utasításrészt elhelyezni. |
-- Már elmentettük az -- ora_sql_txt értékét az -- sql_text változóba. n := ora_partition_pos; uj_utasitas := substr(sql_text, 1, n-1) || ' ' || sajat_part_resz || ' ' || substr(sql_text, n)); |
ora_privileges( privilegium_lista OUT ora_name_list_t) |
BINARY_INTEGER |
Az éppen kapott vagy visszavont jogosultságok számát és listáját határozza meg. |
IF ora_sysevent = 'GRANT' OR ora_sysevent = 'REVOKE' THEN priv_szama := ora_privileges(priv_lista); END IF; |
ora_revokee(felh_list OUT ora_name_list_t) |
BINARY_INTEGER |
Azon felhasználók számát és neveinek listáját határozza meg, akiktől jogosultságokat vontak vissza. |
IF (ora_sysevent = 'REVOKE') THEN felh_szama := ora_revokee(felh_list); END IF; |
ora_server_error( pozicio IN NUMBER) |
NUMBER |
A hibaverem megadott pozícióján elhelyezett hibaszámot adja vissza. A verem tetejének pozíciója 1. |
INSERT INTO esemenyek VALUES ('A legutolsó hiba száma: ' || ora_server_error(1)); |
ora_server_error_depth |
BINARY_INTEGER |
A hibaveremben levő összes hiba darabszámát adja vissza. |
n := ora_server_error_depth; |
ora_server_error_msg( pozicio IN BINARY_INTEGER) |
VARCHAR2 |
A hibaverem megadott pozícióján elhelyezett hibához tartozó üzenetet adja vissza. A verem tetejének pozíciója 1. |
INSERT INTO esemenyek VALUES ('A legutolsó hiba: ' || ora_server_error_msg(1)); |
ora_server_error_num_ params( pozicio IN BINARY_INTEGER) |
BINARY_INTEGER |
A hibaverem megadott pozícióján elhelyezett hibához tartozó üzenetben lecserélt "%s" formájú hibaparaméterek számát adja meg. |
n := ora_server_error_num_params (1); |
ora_server_error_param( pozicio IN BINARY_INTEGER, param IN BINARY_INTEGER) |
VARCHAR2 |
A hibaverem megadott pozícióján elhelyezett hibához tartozó üzenetben lecserélt "%s", "%d" formájú hibaparaméterek számát adja meg. |
param := ora_server_error_param(1, 2); |
ora_sql_txt(sql_text OUT ora_name_list_t) |
BINARY_INTEGER |
Meghatározza a triggert aktivizáló utasítás szövegét. Ha az utasítás túl hosszú, akkor több táblasorra tördelődik. A visszatérési érték a tábla sorainak száma. |
DECLARE sql_text ora_name_list_t; stmt VARCHAR2(2000); ... n := ora_sql_txt(sql_text); FOR i IN 1..n LOOP stmt := stmt || sql_text(i); END LOOP; INSERT INTO esemenyek VALUES ('Az aktiváló utasítás: ' || stmt); ... |
ora_sysevent |
VARCHAR2(20) |
A triggert aktivizáló redszeresemény. |
INSERT INTO esemenyek VALUES (ora_sysevent); |
ora_with_grant_option |
BOOLEAN |
Igazzal tér vissza, ha a GRANT utasításban szerepel a WITH GRANT OPTION utasításrész. |
IF ora_sysevent = 'GRANT' AND ora_with_grant_option THEN INSERT INTO esemenyek VALUES ('WITH GRANT OPTION'); END IF; |
space_error_info( |
BOOLEAN |
Igazzal tér vissza, ha valamely objektum számára elfogyott a hely. Az OUT paraméterek adnak információt az objektumról |
IF space_error_info(hsz, |