Adatbázisok szerver oldali programozása Előadás, 2006.03.24.

A VIK Wikiből
(AdatbServerProgJegyzet20060324 szócikkből átirányítva)

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>


<< Előadás, 2006.03.24. >>

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.