Trigger in ORACLE 8 Gennaio 2003 Silvia Chiusano, Paolo Garza 1
Transcript
Trigger in ORACLE 8 Gennaio 2003 Silvia Chiusano, Paolo Garza 1
Trigger in ORACLE 8 Gennaio 2003 Creazione di un trigger CREATE TRIGGER nome_trigger modo evento [OR evento] ON tabella [REFERENCING referenza] [FOR EACH ROW] [WHEN (predicato SQL)] Sviluppo ed utilizzo dei trigger in Oracle blocco PL/SQL; / Silvia Chiusano Paolo Garza Politecnico di Torino 1 Modo 2 Evento • AFTER Il corpo (blocco PL/SQL) 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 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 FOR EACH ROW 4 WHEN • Determina se il trigger è di tipo • Per i row trigger è possibile indicare ulteriori condizioni di attivazione (vincoli di tupla) – ROW TRIGGER • Il predicato SQL viene valutato per ogni tupla – STATEMENT TRIGGER (default) • Non può essere usato per gli statement trigger • 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 Silvia Chiusano, Paolo Garza 6 1 Trigger in ORACLE 8 Gennaio 2003 Accesso alle tuple della tabella associata al trigger Blocco PL/SQL • 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 • Sequenza di operazioni da svolgere in seguito all’attivazione del trigger • [DECLARE dichiarazioni ] BEGIN codice PL/SQL [EXCEPTION gestione eccezioni ] END; / 7 Uso di NEW e OLD 8 Gestione rollback • Nella WHEN del trigger – NEW.nome_campo – OLD.nome_campo • Nel codice PL/SQL (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 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 11 Silvia Chiusano, Paolo Garza 10 DROP TRIGGER nome_trigger; 12 2 Trigger in ORACLE 8 Gennaio 2003 Esempio 1 Esempio 1 • Si considerino le seguenti tabelle: EMP(EMPNO, ENAME , JOB, SAL); 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 BEGIN INSERT INTO emp_logs (log_date,action) VALUES (SYSDATE, ‘UPDATE EMP’); END; / 13 Esempio 1 14 Esempio 1 • 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) CREATE TRIGGER up_row_emp AFTER UPDATE ON emp FOR EACH ROW BEGIN INSERT INTO emp_logr (log_date,action) VALUES (SYSDATE, ‘UPDATE EMP’); END; / 15 Esempio 2 Esempio 2 • Si considerino le tabelle: EMP(EMPNO, ENAME , JOB, SAL); 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 Silvia Chiusano, Paolo Garza 16 18 3 Trigger in ORACLE 8 Gennaio 2003 Esempio 2 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’ CREATE TRIGGER INS_EMP AFTER INSERT ON emp FOR EACH ROW DECLARE minSal NUMBER(7,2); BEGIN SELECT MIN(LOSAL) INTO minSal FROM SALGRADE; IF (:NEW.SAL < minSal) THEN raise_application_error(-20500, ‘Salario troppo basso per ’||:NEW.ENAME); END IF; END; / EMP ( EMPNO, ENAME , JOB, SAL) COPY_CLERK (EMPNO, ENAME, SAL) 19 Esempio 3 - Consistenza tra una base di dati e le repliche 20 Esempio 3 - INSERT • 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. • 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 for each row when (NEW.JOB = 'CLERK') begin insert into COPY_CLERK values (:NEW.EMPNO, :NEW.ENAME, :NEW.SAL); end; / 21 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 for each row when (OLD.JOB = 'CLERK') begin delete from COPY_CLERK where EMPNO=:OLD.EMPNO; end; / create trigger UP_ROW after UPDATE OF empno, ename, job, sal ON EMP for each row begin if ( (:NEW.JOB = 'CLERK') and (:OLD.JOB!='CLERK')) then INSERT into copy_clerk values (:NEW.empno, :NEW.ename, :NEW.sal); end if; 23 Silvia Chiusano, Paolo Garza 24 4 Trigger in ORACLE 8 Gennaio 2003 Esempio 3 - UPDATE (2) if ( (:OLD.JOB = 'CLERK') and (:NEW.JOB!='CLERK')) then DELETE from copy_clerk where empno=:OLD.empno; end if; 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; end if; end; / Esempio 4 • Si considerino le tabelle: EMP(EMPNO, ENAME , JOB, SAL); AUMENTI_SALARIO(EMPNO,DATA,AUMENTO); 25 26 Esempio 4 Esempio 4 • 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 CREATE TRIGGER UP_EMP AFTER UPDATE OF SAL ON emp FOR EACH ROW WHEN (NEW.sal>OLD.sal) DECLARE nAumenti NUMBER; BEGIN 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; END; / 27 Silvia Chiusano, Paolo Garza 28 5