Cviceni 8
--TRIGGERY
--
--Trigger je kod, ktery je automaticky spusten pri nejake udalosti. Touto
--udalosti mohou byt systemove akce typu prihlaseni apod. Pro bezne uzivatele
--jsou nejdulezitejsi udalosti vazici se k modifikaci dat v tabulce.
--
--Syntax:
--
--CREATE [OR REPLACE] TRIGGER jmeno {BEFORE|AFTER|INSTEAD OF}
--udalost [REFERENCING OLD AS o NEW AS n] [FOR EACH ROW] [WHEN (podminka)]
--blok
--
--Udalost muze vypadat jako OR nasledujicich moznosti:
--DELETE
--INSERT
--UPDATE [OF sloupec, ...]
--ON tabulka
--
--INSTEAD OF triggery nas ted nezajimaji (slouzi pro pohledy),
--BEFORE triggery jsou spousteny pred provedenim udalosti,
--AFTER triggery jiz po provedeni udalosti.
--
--Trigger je spusten budto jednou pri provadeni prikazu (default) nebo pro
--kazdy meneny radek (FOR EACH ROW).
--
--[Pro triggery typu FOR EACH ROW]
--Pri zmene mam k dispozici promenne :new s novou hodnotou a :old s puvodni
--hodnotou. BEFORE trigger muze menit hodnoty :new a tim ovlivnovat data.
--(pokud se mi nelibi nazvy new a old (napr. koliduji s nazvy sloupcu),
--mohu si je prejmenovat v klauzuli REFERENCING).
--
--Trigger je spusten jen, je-li splnena podminka v casti WHEN.
--
--Podminky: INSERTING, UPDATING, DELETING
--
--IF INSERTING THEN . . . END IF;
--IF UPDATING THEN . . . END IF;
--IF DELETING THEN . . . END IF;


SQL> DROP TABLE platy;
SQL> CREATE TABLE platy(uco NUMBER, uvazek NUMBER, sazba NUMBER, plat NUMBER);

-- Trigger pro aktualizaci platu podle sazby a uvazku:
CREATE OR REPLACE TRIGGER Aktualizuj_plat
BEFORE INSERT OR UPDATE ON platy
FOR EACH ROW
DECLARE
BEGIN
:new.plat:=:new.sazba*:new.uvazek;
END;
/

Trigger created.

SQL> INSERT INTO platy VALUES (1,100,5,0);

1 row created.

SQL> SELECT * FROM platy;

       UCO     UVAZEK      SAZBA       PLAT
---------- ---------- ---------- ----------
         1        100          5        500

-- Trigger pro hlidani, aby uvazek nebyl vyssi nez 200
CREATE OR REPLACE TRIGGER Hlidej_plat
BEFORE INSERT OR UPDATE OF uvazek ON platy
FOR EACH ROW
DECLARE
BEGIN
IF :new.uvazek>200 THEN :new.uvazek:=200;
END IF;
END;
/

Trigger created.

-- trigger opravi hodnotu uvazku na 200 pri vkladani
SQL> INSERT INTO platy VALUES (3,500,400,0);

1 row created.

SQL> SELECT * FROM platy;

       UCO     UVAZEK      SAZBA       PLAT
---------- ---------- ---------- ----------
         1        100          5        500
         3        200        400      80000

-- trigger opravi hodnotu uvazku na 200 pri ukatualizace jiz vlozene polozky
SQL> UPDATE platy SET uvazek=400 WHERE uco=1;

1 row updated.

SQL> SELECT * FROM platy;

       UCO     UVAZEK      SAZBA       PLAT
---------- ---------- ---------- ----------
         1        200          5       1000
         3        200        400      80000

-- Priklad: logovani zmeny platu
SQL> DROP TABLE platy_log;
SQL> CREATE TABLE platy_log(kdy DATE, uco NUMBER, puvodni NUMBER, novy NUMBER);

CREATE OR REPLACE TRIGGER loguj_zmeny_platu
AFTER INSERT OR DELETE OR UPDATE ON platy
FOR EACH ROW
DECLARE
BEGIN
INSERT INTO platy_log VALUES(sysdate,:new.uco,:old.plat,:new.plat);
END;
/

Trigger created.

-- spusteni trigerru
SQL> INSERT INTO platy VALUES (4,100,10,0);

1 row created.

SQL> SELECT * FROM platy_log;

KDY              UCO    PUVODNI       NOVY
--------- ---------- ---------- ----------
12-APR-05          4                  1000

SQL> DROP TABLE platy_log2;
SQL> CREATE TABLE platy_log2(kdy DATE, uco NUMBER, typ_zmeny VARCHAR2(20));

-- Trigger pro logovani typu upravy
CREATE OR REPLACE TRIGGER loguj_zmeny
AFTER INSERT OR DELETE OR UPDATE ON platy
FOR EACH ROW
DECLARE
BEGIN
if INSERTING then
INSERT INTO platy_log2 VALUES(sysdate,:new.uco,'Insert');
end if;
if UPDATING then
INSERT INTO platy_log2 VALUES(sysdate,:old.uco,'Update');
end if;
if DELETING then
INSERT INTO platy_log2 VALUES(sysdate,:old.uco,'Delete');
end if;
END;
/

Trigger created.

-- spusteni trigerru
SQL> INSERT INTO platy VALUES (5,100,10,0);

1 row created.

SQL> UPDATE platy SET uvazek = 150 WHERE uco = 3;

1 row updated.

SQL> DELETE FROM platy;

4 rows deleted.

SQL> SELECT * FROM platy_log2;

KDY              UCO TYP_ZMENY
--------- ---------- --------------------
12-APR-05          5 Insert
12-APR-05          3 Update
12-APR-05          1 Delete
12-APR-05          3 Delete
12-APR-05          4 Delete
12-APR-05          5 Delete

6 rows selected.