Egy trigger létrehozásához saját sémában a CREATE TRIGGER, másik felhasználó sémájában a CREATE ANY TRIGGER, az adatbázison létrehozandóhoz pedig az ADMINISTER DATABASE TRIGGER jogosultság szükséges. A létrehozó utasítás formája:
CREATE [OR REPLACE] TRIGGER [séma.]triggernév
{BEFORE|AFTER|INSTEAD OF}
{dml_trigger|{ddl_esemény [OR ddl_esemény]…|
ab_esemény [OR ab_esemény]…}
ON {DATEBASE|[séma.]SCHEMA}
[WHEN (feltétel)] {plsql_blokk|eljáráshívás}
ahol
dml_trigger::=
{INSERT|DELETE|UPDATE [OF oszlop [,oszlop]…}
[OR {INSERT|DELETE|UPDATE [OF oszlop [,oszlop]…}]…
ON {[séma.]tábla |
[NESTED TABLE bát_oszlop OF] [séma.]nézet}
[REFERENCING {OLD [AS] régi | NEW [AS] új | PARENT [AS] szülő}
[{OLD [AS] régi | NEW [AS] új | PARENT [AS] szülő}]…
[FOR EACH ROW]
Az OR REPLACE esetén a már létező trigger újradefiniálása történik, annak előzetes megszüntetése nélkül. A séma a triggert tartalmazó séma neve. Ha hiányzik, a parancsot kiadó felhasználó sémájában jön létre a trigger.
A triggernév a most létrehozandó trigger neve lesz.
A BEFORE, AFTER, INSTEAD OF a trigger típusát adja meg. BEFORE és AFTER trigger csak táblán, INSTEAD OF csak nézeten hozható létre.
Az INSERT, DELETE, UPDATE definiálja azt az SQL utasítást, amelynek hatására a trigger lefut. UPDATE trigger esetén ha megadunk oszlopokat az OF kulcsszó után, akkor a trigger csak az olyan UPDATE utasítás hatására fut le, amely SET utasításrészében legalább az egyik megadott oszlop szerepel.
Az ON utasításrész azt az adatbázis-objektumot adja meg, amelyen a triggert létrehozzuk. Ez a megadott séma (vagy a létrehozó sémája) tábla, nézet vagy beágyazott tábla típusú oszlop (bát_oszlop) lehet.
A REFERENCING utasításrész korrelációs neveket (régi, új, szülő) határoz meg. Ezek a trigger törzsében és a WHEN utasításrészben használhatók sorszintű trigger esetén. Az OLD az aktuális sor módosítása előtti, a NEW a módosítása utáni neveket adja meg. Alapértelmezett korrelációs nevek :OLD és :NEW. Beágyazott tábla esetén az OLD és a NEW a beágyazott tábla sorait, a PARENT a szülő tábla aktuális sorát adja. Objektumtábla és objektumnézet esetén az OLD és NEW az objektumpéldányt hivatkozza.
A FOR EACH ROW sor szintű triggert hoz létre. Ha nem adjuk meg, akkor az INSTEAD OF trigger (amelynél ez az alapértelmezés) kivételével utasítás szintű trigger jön létre. A ddl_esemény egy olyan DDL utasítást, az ab_esemény egy olyan adatbázis-eseményt határoz meg, amelyek a triggert aktiválják. Ezek az adatbázishoz (DATABASE) vagy a séma nevű (ennek hiányában a saját) sémához (SCHEMA) köthetők. BEFORE vagy AFTER triggerek esetén adhatók meg.
A ddl_esemény a következők valamelyike lehet: ALTER, ANALYZE, ASSOCIATE STATISTICS, AUDIT, COMMENT, CREATE, DISASSOCIATE STATISTICS, DROP, GRANT, NOAUDIT, RENAME, REVOKE, TRUNCATE. Megadásuk esetén az általuk megnevezett parancs végrehajtása jelenti a triggert aktivizáló eseményt.
Ha azt akarjuk, hogy a fenti parancsok mindegyikére reagáljon a trigger, akkor adjuk meg a DDL opciót.
Az ALTER DATABASE, CREATE DATABASE és CREATE CONTROLFILE parancsok nem aktivizálják a triggert.
Az ab_esemény az alábbi opciókkal rendelkezik: SERVERERROR: egy szerverhiba bekövetkezte aktiválja a triggert. A következő hibák esetén a trigger nem fog lefutni:
ORA-01403: nem talált adatot,
ORA-01422: a pontos lehívás (FETCH) a kívántnál több sorral tér vissza,
ORA-01423: hiba a többlet sorok ellenőrzésénél a pontos lehívásban (FETCH),
ORA-01034: az ORACLE nem érhető el,
ORA-04030: a feldolgozás kifutott a memóriából (,) lefoglalása közben.
LOGON: egy kliensalkalmazás bejelentkezik az adatbázisba.
LOGOFF: egy kliensalkalmazás kilép az adatbázisból.
STARTUP: az adatbázis megnyitásra kerül.
SHUTDOWN: az adatbázis leállításra kerül.
SUSPEND: szerverhiba miatt egy tranzakció működése felfüggesztődik.
AFTER trigger esetén csak a LOGON, STARTUP, SERVERERROR, SUSPEND; BEFORE triggernél a LOGOFF és SHUTDOWN megadása lehetséges. Az AFTER STARTUP és a BEFORE SHUTDOWN triggerek csak adatbázison értelmezhetők.
A trigger csak a WHEN utasításrészben megadott feltétel teljesülése esetén fut le. A feltételben nem szerepelhet lekérdezés vagy PL/SQL függvény hívása. INSTEAD OF és utasításszintű trigger esetén nem adható meg.
A plsql_blokk vagy az eljáráshívás a trigger törzsét alkotják. Ez tehát vagy egy név nélküli PL/SQL blokk, vagy egy tárolt eljárás meghívása.
A következőkben példákat adunk különböző triggerekre.
DML triggerek
1. példa
/*
A következő trigger segítségével a kölcsönzés
adminisztrácója automatizálható.
Ugyanis egyetlen sor beszúrása a kolcsonzes táblába
maga után vonja az ugyfel és a konyv táblák megfelelő
bejegyzéseinek változtatását.
A trigger sor szintű. Ha nem lehet a kölcsönzést
végrehajtani, kivételt dobunk.
*/
CREATE OR REPLACE TRIGGER tr_insert_kolcsonzes
AFTER INSERT ON kolcsonzes
FOR EACH ROW
DECLARE
v_Ugyfel ugyfel%ROWTYPE;
BEGIN
SELECT * INTO v_Ugyfel
FROM ugyfel WHERE id = :NEW.kolcsonzo;
IF v_Ugyfel.max_konyv = v_Ugyfel.konyvek.COUNT THEN
RAISE_APPLICATION_ERROR(-20010,
v_Ugyfel.nev || ' ügyfél nem kölcsönözhet több könyvet.');
END IF;
INSERT INTO TABLE(SELECT konyvek FROM ugyfel
WHERE id = :NEW.kolcsonzo)
VALUES (:NEW.konyv, :NEW.datum);
BEGIN
UPDATE konyv SET szabad = szabad -1
WHERE id = :NEW.konyv;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20020,
'Nincs a könyvből több példány.');
END;
END tr_insert_kolcsonzes;
/
show errors
/* Nézzünk néhány példát.
A példák az inicializált adatbázis adatain futnak. */
/*
József István és az 'SQL:1999 ...' könyv
Sajnos az ügyfél nem kölcsönözhet többet.
*/
INSERT INTO kolcsonzes (kolcsonzo, konyv, datum)
VALUES (15, 30, SYSDATE);
/*
Hiba a(z) 1. sorban:
INSERT INTO kolcsonzes (kolcsonzo, konyv, datum)
*
ORA-20010: József István ügyfél nem kölcsönözhet több könyvet.
ORA-06512: a(z) "PLSQL.TR_INSERT_KOLCSONZES", helyen a(z) 8. sornál
ORA-04088: hiba a(z) 'PLSQL.TR_INSERT_KOLCSONZES' trigger futása közben
*/
/*
Komor Ágnes és az 'A critical introduction… ' könyv
Sajnos a könyvből nincs szabad példány.
*/
INSERT INTO kolcsonzes (kolcsonzo, konyv, datum)
VALUES (30, 35, SYSDATE);
/*
Hiba a(z) 1. sorban:
INSERT INTO kolcsonzes (kolcsonzo, konyv, datum)
*
ORA-20020: Nincs a könyvből több példány.
ORA-06512: a(z) "PLSQL.TR_INSERT_KOLCSONZES", helyen a(z) 21. sornál
ORA-04088: hiba a(z) 'PLSQL.TR_INSERT_KOLCSONZES' trigger futása közben
*/
/*
Komor Ágnes és a 'The Norton Anthology… ' könyv
Minden rendben lesz.
*/
INSERT INTO kolcsonzes (kolcsonzo, konyv, datum)
VALUES (30, 40, SYSDATE);
SELECT * FROM TABLE(SELECT konyvek FROM ugyfel
WHERE id = 30);
/*
1 sor létrejött.
KONYV_ID DATUM
---------- -----------
5 02-ÁPR. 12
10 02-MÁRC. 12
40 02-MÁJ. 12
*/
2. példa
/* A következő trigger segítségével naplózzuk
a törölt kölcsönzéseket a kolcsonzes_naplo táblában. */
CREATE OR REPLACE TRIGGER tr_kolcsonzes_naploz
AFTER DELETE ON kolcsonzes
REFERENCING OLD AS kolcsonzes
FOR EACH ROW
DECLARE
v_Konyv konyv%ROWTYPE;
v_Ugyfel ugyfel%ROWTYPE;
BEGIN
SELECT * INTO v_Ugyfel
FROM ugyfel WHERE id = :kolcsonzes.kolcsonzo;
SELECT * INTO v_Konyv
FROM konyv WHERE id = :kolcsonzes.konyv;
INSERT INTO kolcsonzes_naplo VALUES(
v_Konyv.ISBN, v_Konyv.cim,
v_Ugyfel.nev, v_Ugyfel.anyja_neve,
:kolcsonzes.datum, SYSDATE,
:kolcsonzes.megjegyzes);
END tr_kolcsonzes_naploz;
/
show errors
3. példa
/* A következő trigger megakadályozza, hogy
egy könyvet 2-nél többször meghosszabítsanak.
Megjegyzés:
- A WHEN feltételében nem kell ':' az OLD, NEW, PARENT elé.
- Ugyanez a hatás elérhető egy CHECK megszorítással. */
CREATE OR REPLACE TRIGGER tr_kolcsonzes_hosszabbit
BEFORE INSERT OR UPDATE ON kolcsonzes
FOR EACH ROW
WHEN (NEW.hosszabbitva > 2 OR NEW.hosszabbitva < 0)
BEGIN
RAISE_APPLICATION_ERROR(-20005,
'Nem megengedett a hosszabbítások száma');
END tr_kolcsonzes_hosszabbit;
/
show errors
UPDATE kolcsonzes SET hosszabbitva = 10;
/*
Hiba a(z) 1. sorban:
UPDATE kolcsonzes SET hosszabbitva = 10
*
ORA-20005: Nem megengedett a hosszabbítások száma
ORA-06512: a(z) "PLSQL.TR_KOLCSONZES_HOSSZABBIT", helyen a(z) 2. sornál
ORA-04088: hiba a(z) 'PLSQL.TR_KOLCSONZES_HOSSZABBIT' trigger futása közben
*/
4. példa
/* Egy triggerrel megakadályozzuk azt, hogy valaki a kolcsonzes_naplo
táblából töröljön, vagy az ott levő adatokat módosítsa.
Nincs szükség sor szintű triggerre, elég utasítás szintű trigger. */
CREATE OR REPLACE TRIGGER tr_kolcsonzes_naplo_del_upd
BEFORE DELETE OR UPDATE ON kolcsonzes_naplo
BEGIN
RAISE_APPLICATION_ERROR(-20100,
'Nem megengedett művelet a kolcsonzes_naplo táblán');
END tr_kolcsonzes_naplo_del_upd;
/
5. példa
/* A NEW pszeudováltozó értéke megváltoztatható BEFORE triggerben,
és akkor az új érték kerül be a táblába. */
CREATE TABLE szam_tabla(a NUMBER);
CREATE OR REPLACE TRIGGER tr_duplaz
BEFORE INSERT ON szam_tabla
FOR EACH ROW
BEGIN
:NEW.a := :NEW.a * 2;
END tr_duplaz;
/
INSERT INTO szam_tabla VALUES(5);
SELECT * FROM szam_tabla;
/*
A
----------
10
*/
DROP TRIGGER tr_duplaz;
DROP TABLE szam_tabla;
6. példa
/* Egy könyv azonosítóját kell megváltoztatni.
Ez nem lehetséges automatikusan, mert
a kolcsonzes tábla konyv oszlopa külső kulcs.
Így azt is meg kell változtatni, hogy
az integritási megszorítás ne sérüljön.
A megszorítás a trigger futása után kerül ellenőrzésre. */
CREATE OR REPLACE TRIGGER tr_konyv_id
BEFORE UPDATE OF id ON konyv
FOR EACH ROW
BEGIN
-- Módosítjuk a kolcsonzes táblát
UPDATE kolcsonzes SET konyv = :NEW.id
WHERE konyv = :OLD.id;
END tr_konyv_id;
/
show errors;
UPDATE konyv SET id = 6 WHERE id = 5;
INSTEAD OF triggerek
1. példa
/* Az INSTEAD OF triggerek lehetővé teszik nézetek módosítását.
Megpróbáljuk módosítani egy ügyfél nevét az ugyfel_konyv
nézet sorain keresztül. */
UPDATE ugyfel_konyv SET ugyfel = 'József István TRIGGERES'
WHERE ugyfel_id = 15;
/*
Hiba a(z) 1. sorban:
UPDATE ugyfel_konyv SET ugyfel = 'József István TRIGGERES'
*
ORA-01779: nem módosítható olyan oszlop, amely egy kulcsot nem megőrző táblára utal
*/
/* A következő trigger segítségével egy ügyfél nevét vagy
egy könyv címét módosíthatjuk az ugyfel_konyv nézeten keresztül.
Ha azonosítót is megpróbálnak változtatni,
azzal egyszerűen nem törődünk (nem váltunk ki kivételt).*/
CREATE OR REPLACE TRIGGER tr_ugyfel_konyv_mod
INSTEAD OF UPDATE ON ugyfel_konyv
FOR EACH ROW
BEGIN
IF :NEW.ugyfel <> :OLD.ugyfel THEN
UPDATE ugyfel SET nev = :NEW.ugyfel
WHERE id = :OLD.ugyfel_id;
END IF;
IF :NEW.konyv <> :OLD.konyv THEN
UPDATE konyv SET cim = :NEW.konyv
WHERE id = :OLD.konyv_id;
END IF;
END tr_ugyfel_konyv_mod;
/
show errors
/* Megpróbálunk módosítani megint. */
UPDATE ugyfel_konyv SET ugyfel = 'József István TRIGGERES'
WHERE ugyfel_id = 15;
/*
5 sor módosítva.
*/
2. példa
/* Az INSTEAD OF triggerek használhatók NESTED TABLE opcióval,
egy nézet kollekcióoszlopának módosítására.
NESTED TABLE előírás csak nézetek esetében használható,
táblák kollekció típusú oszlopaira nem.
Megadunk egy nézetet, amely egy alkérdés eredményét
kollekció típusú oszlopként mutatja. */
CREATE VIEW ugyfel_kolcsonzes AS
SELECT u.id, u.nev, CAST( MULTISET( SELECT konyv, datum
FROM kolcsonzes
WHERE kolcsonzo = u.id) AS T_Konyvek) AS konyvek
FROM ugyfel u;
/* Töröljük József István 'ECOOP 2001...' kölcsönzését */
DELETE FROM TABLE(SELECT konyvek FROM ugyfel_kolcsonzes WHERE id = 15)
WHERE konyv_id = 25;
/*
Hiba a(z) 1. sorban:
DELETE FROM TABLE(SELECT konyvek FROM ugyfel_kolcsonzes
*
ORA-25015: ezen a beágyazott táblanézet oszlopon nem hajtható végre DML
*/
/* A következő trigger segítségével a visszahozatal adminisztrácója
automatizálható az ugyfel_kolcsonzes tábla konyvek oszlopán keresztül.
Ugyanis egyetlen sor törlése a beágyazott táblából
előidézi a kolcsonzes tábla egy sorának törlését,
az ugyfel tábla konyvek oszlopának módosítását,
valamint a konyv tábla megfelelő bejegyzésének változtatását. */
CREATE OR REPLACE TRIGGER tr_ugyfel_kolcsonzes_del
INSTEAD OF DELETE ON NESTED TABLE konyvek OF ugyfel_kolcsonzes
FOR EACH ROW
BEGIN
DELETE FROM TABLE(SELECT konyvek FROM ugyfel WHERE id = :PARENT.id)
WHERE konyv_id = :OLD.konyv_id
AND datum = :OLD.datum;
DELETE FROM kolcsonzes
WHERE kolcsonzo = :PARENT.id
AND konyv = :OLD.konyv_id
AND datum = :OLD.datum;
UPDATE konyv SET szabad = szabad + 1
WHERE id = :OLD.konyv_id;
END tr_ugyfel_kolcsonzes_del;
/
show errors
/* Töröljük József István 'ECOOP 2001...' kölcsönzését */
DELETE FROM TABLE(SELECT konyvek FROM ugyfel_kolcsonzes WHERE id = 15)
WHERE konyv_id = 25;
/*
1 sor törölve.
*/
/* A trigger végrehajtott egy DELETE utasítást a kolcsonzes táblán.
Ellenőrizzük, hogy a korábban létrehozott
tr_kolcsonzes_naploz trigger is lefutott-e? */
SELECT * FROM kolcsonzes_naplo;
/*
KONYV_ISBN KONYV_CIM UGYFEL_NEV UGYFEL_ANYJANEVE ELVITTE VISSZAHOZTA MEGJEGYZES
------------------ ------------- ------------- ----------------- ----------- ----------- -------------
ISBN 963 03 9005 1 Java - start! József István Ábrók Katalin 02-ÁPR. -10 06-JÚN. -23
(Megj.: Az eredmény formátumát kisebb méretűvé szabtuk át
az olvashatóság kedvéért.) */
3. példa (Korrelációs nevek használatára)
/* Triggereink olvashatóbbak lehetnek, ha az
alapértelmezett NEW, OLD, illetve PARENT nevekre
azok szemantikájának megfelelő névvel hivatkozunk.
Ezt a REFERENCING előírással adhatjuk meg.
Lássuk egy előző példa módosított változatát: */
CREATE OR REPLACE TRIGGER tr_ugyfel_kolcsonzes_del
INSTEAD OF DELETE ON NESTED TABLE konyvek OF ugyfel_kolcsonzes
REFERENCING OLD AS v_Kolcsonzes
PARENT AS v_Ugyfel
FOR EACH ROW
BEGIN
DELETE FROM TABLE(SELECT konyvek FROM ugyfel WHERE id = :v_Ugyfel.id)
WHERE konyv_id = :v_Kolcsonzes.konyv_id
AND datum = :v_Kolcsonzes.datum;
DELETE FROM kolcsonzes
WHERE kolcsonzo = :v_Ugyfel.id
AND konyv = :v_Kolcsonzes.konyv_id
AND datum = :v_Kolcsonzes.datum;
UPDATE konyv SET szabad = szabad + 1
WHERE id = :v_Kolcsonzes.konyv_id;
END tr_ugyfel_kolcsonzes_del;
/
show errors
/* Döntse el, melyik forma tetszik jobban, és használja azt következetesen!
A könyv további részeiben maradunk a standard nevek mellett. */
4. példa (Trigger, ahol a törzs egyetlen eljáráshívásból áll)
/* Az előzőek során létrehozott tr_ugyfel_kolcsonzes_del
egy könyv visszahozatalát adminisztrálta.
Ugyanezt a funkciót már megírtuk egy csomagbeli eljárással.
Célszerűbb lenne azt használni, a kód újrahasználása végett. */
CREATE OR REPLACE TRIGGER tr_ugyfel_kolcsonzes_del
INSTEAD OF DELETE ON NESTED TABLE konyvek OF ugyfel_kolcsonzes
FOR EACH ROW
CALL konyvtar_csomag.visszahoz(:PARENT.id, :OLD.konyv_id)
/
DDL trigger a PLSQL sémára
Példa
/* Egy csomagváltozóban számláljuk a munkamenetben végrehajtott
sikeres és sikertelen CREATE és DROP utasításokat.
*/
CREATE OR REPLACE PACKAGE ddl_szamlalo IS
v_Sikeres_create NUMBER := 0;
v_Sikertelen_create NUMBER := 0;
v_Sikeres_drop NUMBER := 0;
v_Sikertelen_drop NUMBER := 0;
PROCEDURE kiir;
END ddl_szamlalo;
/
CREATE OR REPLACE PACKAGE BODY ddl_szamlalo IS
PROCEDURE kiir IS
BEGIN
DBMS_OUTPUT.PUT_LINE(RPAD('v_Sikeres_create: ', 25)
|| v_Sikeres_create);
DBMS_OUTPUT.PUT_LINE(RPAD('v_Sikertelen_create: ', 25)
|| v_Sikertelen_create);
DBMS_OUTPUT.PUT_LINE(RPAD('v_Sikeres_drop: ', 25)
|| v_Sikeres_drop);
DBMS_OUTPUT.PUT_LINE(RPAD('v_Sikertelen_drop: ', 25)
|| v_Sikertelen_drop);
END kiir;
END ddl_szamlalo;
/
CREATE OR REPLACE TRIGGER tr_ddl_szamlalo_bef
BEFORE CREATE OR DROP
ON plsql.SCHEMA
BEGIN
/* Pesszimistán feltételezzük, hogy a
kiváltó utasítás nem lesz sikeres */
IF ORA_SYSEVENT = 'CREATE' THEN
ddl_szamlalo.v_Sikertelen_create :=
ddl_szamlalo.v_Sikertelen_create + 1;
ELSE
ddl_szamlalo.v_Sikertelen_drop :=
ddl_szamlalo.v_Sikertelen_drop + 1;
END IF;
END tr_ddl_szamlalo_bef;
/
CREATE OR REPLACE TRIGGER tr_ddl_szamlalo_aft
AFTER CREATE OR DROP
ON plsql.SCHEMA
BEGIN
/* Nem kellett volna pesszimistának lenni:) */
IF ORA_SYSEVENT = 'CREATE' THEN
ddl_szamlalo.v_Sikertelen_create :=
ddl_szamlalo.v_Sikertelen_create - 1;
ddl_szamlalo.v_Sikeres_create :=
ddl_szamlalo.v_Sikeres_create + 1;
ELSE
ddl_szamlalo.v_Sikertelen_drop :=
ddl_szamlalo.v_Sikertelen_drop - 1;
ddl_szamlalo.v_Sikeres_drop :=
ddl_szamlalo.v_Sikeres_drop + 1;
END IF;
END tr_ddl_szamlalo_aft;
/
-- Egy sikertelen CREATE
CREATE TRIGGER tr_ddl_szamlalo_aft
/
-- És egy sikeres CREATE
CREATE TABLE abcdefghijklm (a NUMBER)
/
-- És egy sikeres DROP
DROP TABLE abcdefghijklm
/
CALL ddl_szamlalo.kiir();
/*
v_Sikeres_create: 1
v_Sikertelen_create: 1
v_Sikeres_drop: 1
v_Sikertelen_drop: 0
*/
/* Mi lesz az eredmény, ha újra létrehozzuk
a csomag specifikációját?
Magyarázza meg az eredményt! */
CREATE OR REPLACE PACKAGE ddl_szamlalo IS
v_Sikeres_create NUMBER := 0;
v_Sikertelen_create NUMBER := 0;
v_Sikeres_drop NUMBER := 0;
v_Sikertelen_drop NUMBER := 0;
-- ez a megjegyzés itt megváltoztatja a csomagot,
-- ezért tényleg újra létre kell hozni
PROCEDURE kiir;
END ddl_szamlalo;
/
CALL ddl_szamlalo.kiir();
/*
v_Sikeres_create: 1
v_Sikertelen_create: -1
v_Sikeres_drop: 0
v_Sikertelen_drop: 0
*/
Adatbázistrigger
Példa
/* A DBA naplózza a felhasználók be- és kijelentkezéseit
a következő tábla és triggerek segítségével. */
CREATE TABLE felhasznalok_log (
Felhasznalo VARCHAR2(30),
Esemeny VARCHAR2(30),
Hely VARCHAR2(30),
Idopont TIMESTAMP
);
CREATE OR REPLACE PROCEDURE felhasznalok_log_bejegyez(
p_Esemeny felhasznalok_log.esemeny%TYPE
) IS
BEGIN
INSERT INTO felhasznalok_log VALUES (
ORA_LOGIN_USER, p_Esemeny,
ORA_CLIENT_IP_ADDRESS, SYSTIMESTAMP
);
END felhasznalok_log_bejegyez;
/
CREATE OR REPLACE TRIGGER tr_felhasznalok_log_be
AFTER LOGON
ON DATABASE
CALL felhasznalok_log_bejegyez('Bejelentkezés')
/
CREATE OR REPLACE TRIGGER tr_felhasznalok_log_ki
BEFORE LOGOFF
ON DATABASE
CALL felhasznalok_log_bejegyez('Kijelentkezés')
/
/* Próbáljon meg be- és kijelentkezni néhány felhasználóval,
ha teheti különböző kliensekről, majd ellenőrizze a tábla tartalmát. */