Adatbázisok szerver oldali programozása Előadás, 2006.03.24.
Ez az oldal a korábbi SCH wikiről lett áthozva.
Ha úgy érzed, hogy bármilyen formázási vagy tartalmi probléma van vele, akkor, kérlek, javíts rajta egy rövid szerkesztéssel!
Ha nem tudod, hogyan indulj el, olvasd el a migrálási útmutatót.
<style> code.pre { white-space: pre; display:block; mergin-top: 2px; margin-bottom: 2px;} code.precompact { white-space: pre; display:block; mergin-top: 2px; margin-bottom: 2px; line-height: 12px; } li { line-height: 18px; } </style>
Triggerek
A trigger egy adatbázis eseményre automatikusan lefutó tárolt eljárás. Explicite nem hívható.
Típusai:
- DML triggerek: =INSERT=, =UPDATE= vagy =DELETE= eseménzekre fut le
- DDL triggerek: =CREATE=, =ALTER=, =DROP=, =GRANT=, =REVOKE= eseményekre fut le
- Szerver események: Startup, Shutdown
- Felhasználói események: Logon, Logoff
DML triggerek
- esemény lehet: =INSERT=, =UPDATE= vagy =DELETE=
- nézethez vagy táblához rendelhető hozzá
- esemény előtt (
BEFORE
), után (AFTER
) vagy helyett (INSTEAD OF
) fut le - az esemény bekövetkeztekor lefuthat egyszer vagy minden sorra
Szintaktika
CREATE OR REPLACE TRIGGER név
{BEFORE | AFTER || INSTEAD OF} {INSERT || DELETE UPDATE [OF oszlop1, ...]}
[OR további események ...]
ON {táblanév | nézetnév} [FOR EACH ROW]
[WHEN feltétel]
PL/SQL blokk
- Az =INSTEAD OF= csak nézetre használható. Akkor van értelme, ha a nézet több táblából származik. Ilyenkor az Oracle nem támogatja az =INSERT=, =UPDATE= és =DELETE= parancsokat, nekünk kell megírnunk, hogy mi történjen.
- A =BEFORE= és az =AFTER= csak táblára működik.
- Az =UPDATE= trigger alapesetben bármelyik oszlop változása esetén kiváltódik, de az =OF= kulcsszóval szűkíthető kevesebb oszlopra.
- A tábla törlésével a kapcsolódó triggerek is törlődnek
BEFORE használata
- A =BEFORE= az utasítás előtt fut le, ha exceptiont dobunk, az utasítás nem hajtódik végre
- Leggyakoribb célok
- azonosító generálás
- logolás, ha a próbálkozást is naplózzuk (pl. biztonsági log)
- táblaméret korlátozása (
INSERT
előtt, pl. a vizsgára csak 20 ember jelentkezhet) - származtatott mező kitöltése
AFTER használata
- származtatott mező kitöltése másik táblában, mint amire az SQL utasítás hivatkozik
- sikeres műveletek naplózása
Triggerek lefutási sorrendje
- =BEFORE= utasításra vonatkozó trigger
- minden sorra
- =BEFORE= sorra vonatkozó trigger
- utasítás
- =AFTER= sorra vonatkozó trigger
- =AFTER= utasításra vonatkozó trigger
- Ha 1 táblára több azonos típusú trigger is vonatkozik, a lefutási sorrend nem definiált
Hivatkozás az éppen beszúrt vagy törölt adatokra
- csak =FOR EACH ROW= trigger esetén használható
- Beszúrandó (
INSERT</code) vagy módosított (<code>UPDATE
) érték: =:new.oszlopnév= - Módosítandó (
UPDATE</code) vagy törlendőt (<code>DELETE
) érték: =:old.oszlopnév= - A =BEFORE= triggerekben a =:new= értékek írhatók, az =:old= értékek csak olvashatók
- Az =AFTER= triggerekben mindkettő csak olvasható
DDL triggerek
CREATE OR REPLACE TRIGGER név
{BEFORE | AFTER} DDL esemény [OR DDL esemény ...]
ON SCHEMA
[WHEN feltétel]
PL/SQL blokk
Szerver triggerek
CREATE OR REPLACE TRIGGER név
{BEFORE | AFTER} adatbázis esemény [OR adatbázis esemény ...]
ON DATABASE
[WHEN feltétel]
PL/SQL blokk
Példák
ID generálás
CREATE TRIGGER agyag_idtr BEFORE INSERT ON anyag FOR EACH ROW
BEGIN
SELECT anyag_seq.NEXTVAL INTO :new.anyag_id FROM DUAL;
END;
Kurzus létszám korlátozása
Relációs séma:
+------= +----------------+ +-----------+=
| Student |-------|| Student_course ||-------|| Course
|}
+------= +----------------+ +-----------+=
| cou_limit |
|}
+--------==
CREATE OR REPLACE TRIGGER diak_limit
BEFORE INSERT ON student_course FOR EACH ROW
DECLARE
db INT;
dblimit INT;
BEGIN
SELECT count(*) INTO db FROM student_course WHERE sc_courseid = :new.sc_courseid;
SELECT cou_limit INTO dblimit FROM course WHERE cou_id = :new.sc_courseid;
IF db>=dblimit THEN
RAISE_APPLICATION_ERROR(-20111, 'Betelt');
END IF;
END;
Trigger szintű constraintek
TODO:
- Formula 1 relációs séma
- milyen constrainteknek van értelme jelen esetben
- kód a helyezés számítására
-- Peti - 2006.03.27.