Creazione di un trigger Sviluppo ed utilizzo dei trigger in Oracle Silvia Chiusano Paolo Garza CREATE TRIGGER nome_trigger modo evento [OR evento] ON tabella [REFERENCING referenza] [] [WHEN (predicato SQL)] blocco PLSQL; Politecnico di Torino 1 2 Modo AFTER Il corpo (blocco PLSQL) del trigger viene eseguito dopo il comando SQL che ha attivato il trigger BEFORE Il corpo del trigger viene eseguito prima del comando SQL che ha attivato il trigger Evento Il trigger può essere attivato dai seguenti eventi Inserimento di tuple in una tabella: INSERT Cancellazione di tuple da una tabella: DELETE Aggiornamento dei campi di una tabella UPDATE UPDATE of nome_campo Posso associare il trigger a più eventi (elenco di eventi separati da OR) 3 4 WHEN Determina se il trigger è di tipo ROW TRIGGER STATEMENT TRIGGER (default) ROW TRIGGER Il trigger viene attivato per ogni tupla che soddisfa il trigger, relativamente al comando SQL eseguito STATEMENT TRIGGER Il trigger viene attivato una sola volta per il comando SQL cha soddisfa l evento del trigger (non per le singole tuple) 5 Per i row trigger è possibile indicare ulteriori condizioni di attivazione (vincoli di tupla) Il predicato SQL viene valutato per ogni tupla Non può essere usato per gli statement trigger 6 Silvia Chiusano, Paolo Garza 1
Blocco PLSQL Sequenza di operazioni da svolgere in seguito all attivazione del trigger [DECLARE dichiarazioni ] codice PLSQL [EXCEPTION gestione eccezioni ] Accesso alle tuple della tabella associata al trigger Nel corpo di un row trigger si può accedere ai vecchi e nuovi valori delle tuple interessate dal trigger OLD.nome_campo : permette di accedere al vecchio valore del campo nome_campo NEW.nome_campo : permette di accedere al nuovo valore del campo nome_campo OLD.nome_campo è impostato a NULL in caso dell attivazione causata da una INSERT NEW.nome_campo è impostato a NULL in caso dell attivazione causata da una DELETE 7 8 Uso di NEW e OLD Gestione rollback Nella WHEN del trigger NEW.nome_campo OLD.nome_campo Nel codice PLSQL (corpo del trigger) :NEW. nome_campo :OLD. nome_campo Per operare il rollback dell operazione attuale richiamare la procedura raise_application_error(-codice_errore, messaggio_errore); Viene lanciato un errore e quindi in automatico viene operato il rollback dove: codice_errore: codice d errore ritornato all applicazione chiamante messaggio_errore: messaggio di errore ritornato all applicazione chiamante (stringa fra apici singoli) 9 10 Mutating table Cancellazione di un trigger La tabella sul quale il trigger viene scatenato viene chiamata: MUTATING TABLE NON SI PUO USARE in alcun modo tale tabella all interno del corpo del trigger stesso (neppure in lettura) Si puo esclusivamente accedere ai valori della tupla in esame tramite gli operatori NEW e OLD DROP TRIGGER nome_trigger; 11 12 Silvia Chiusano, Paolo Garza 2
Si considerino le seguenti tabelle: EMP_LOGR(LOG_DATE,ACTION); EMP_LOGS(LOG_DATE,ACTION); Sono definiti due trigger sulla tabella EMP CREATE TRIGGER up_stat_emp AFTER UPDATE ON emp INSERT INTO emp_logs (log_date,action) VALUES (SYSDATE, UPDATE EMP ); 13 14 CREATE TRIGGER up_row_emp AFTER UPDATE ON emp INSERT INTO emp_logr (log_date,action) VALUES (SYSDATE, UPDATE EMP ); La tabella EMP contiene 3 record Viene eseguita la seguente operazione SQL: UPDATE emp SET sal=sal+100; Entrambi i trigger vengono attivati L esecuzione dall operazione SQL comporta: la modifica del salario dei 3 record presenti in emp l inserimento di 1 record nella tabella emp_logs (esecuzione del primo trigger) l inserimento di 3 record nella tabella emp_logr (esecuzione del secondo trigger) 15 16 Si considerino le tabelle: SALGRADE(GRADE, LOSAL, HISAL); Scrivere un trigger che non consenta l inserimento di una nuova tupla nella tabella EMP se il salario e inferiore al valore minimo assunto dal campo LOSAL nella tabella SALGRADE Se si tenta di effettuare un inserimento nella tabella EMP usando una salario (SAL) inferiore a quello consentito fare il rollback dell operazione 17 18 Silvia Chiusano, Paolo Garza 3
CREATE TRIGGER INS_EMP AFTER INSERT ON emp DECLARE minsal NUMBER(7,2); SELECT MIN(LOSAL) INTO minsal FROM SALGRADE; IF (:NEW.SAL < minsal) THEN raise_application_error(-20500, Salario troppo basso per :NEW.ENAME); END IF; Esempio 3 Si consideri la base di dati EMP e la base di dati COPY_CLERK contenente una copia delle tuple di emp relative agli impiegati per cui JOB= CLERK EMP ( EMPNO, ENAME, JOB, SAL) COPY_CLERK (EMPNO, ENAME, SAL) 19 20 Esempio 3 - Consistenza tra una base di dati e le repliche Per garantire la consistenza tra la base di dati EMP e la sua replica COPY_CLERK, e necessario propagare a COPY_CLERK ogni inserimento, cancellazione, aggiornamento eseguito su EMP, nel caso in cui le tuple modificate abbiano JOB= CLERK. Tale propagazione puo essere eseguita mediante un trigger. 21 Esempio 3 - INSERT Il seguente trigger inserisce in COPY_CLERK le tuple che sono inserite in EMP, se in tali tuple job= CLERK create trigger INS_ROW after insert on EMP when (NEW.JOB = 'CLERK') insert into COPY_CLERK values (:NEW.EMPNO, :NEW.ENAME, :NEW.SAL); 22 Esempio 3 - DELETE Esempio 3 - UPDATE Il seguente trigger cancella da COPY_CLERK le tuple che sono cancellate da EMP, se in tali tuple job= CLERK Il seguente trigger aggiorna COPY_CLERK se vengono fatti degli aggiornamenti nella tabella EMP, se OLD.job= CLERK o se NEW.job= CLERK create trigger DEL_ROW after delete on EMP when (OLD.JOB = 'CLERK') delete from COPY_CLERK where EMPNO=:OLD.EMPNO; 23 create trigger UP_ROW after UPDATE OF empno, ename, job, sal ON EMP if ( (:NEW.JOB = 'CLERK') and (:OLD.JOB!='CLERK')) then INSERT into copy_clerk values (:NEW.empno, :NEW.ename, :NEW.sal); 24 Silvia Chiusano, Paolo Garza 4
Esempio 3 - UPDATE (2) if ( (:OLD.JOB = 'CLERK') and (:NEW.JOB!='CLERK')) then DELETE from copy_clerk where empno=:old.empno; if ((:OLD.JOB = 'CLERK') and (:NEW.JOB='CLERK')) then UPDATE copy_clerk set ename=:new.ename, empno=:new.empno, sal=:new.sal where empno=:old.empno; 25 Si considerino le tabelle: AUMENTI_SALARIO(EMPNO,DATA,AUMENTO); 26 Scrivere un trigger che non permetta di aumentare il salario agli impiegati che hanno gia avuto almeno 3 aumenti di stipendio. Nella tabella AUMENTI_SALARIO sono memorizzate le informazioni sulle date in cui ogni impiegato ha ricevuto degli aumenti di stipendio Se si cerca di aumentare lo stipendio (campo SAL della tabella EMP) di un impiegato che ha gia avuto almeno 3 aumenti fare il rollback dell operazione 27 CREATE TRIGGER UP_EMP AFTER UPDATE OF SAL ON emp WHEN (NEW.sal>OLD.sal) DECLARE naumenti NUMBER; SELECT COUNT(*) INTO naumenti FROM AUMENTI_SALARIO WHERE empno=:new.empno; IF ( naumenti>2) THEN raise_application_error(-20500, L impiegato :NEW.ename ha ricevuto troppi aumenti ); END IF; 28 Silvia Chiusano, Paolo Garza 5