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