# Trigger (basi di dati)

Il trigger, nelle basi di dati, è una procedura che viene eseguita in maniera automatica in coincidenza di un determinato evento, come ad esempio la cancellazione di un record di una tabella. In questo modo si ha a disposizione una tecnica per specificare e mantenere vincoli di integrità anche complessi. I trigger permettono agli utenti di specificare vincoli di integrità più complessi dato che un trigger è essenzialmente una procedura PL/SQL (Oracle), Transact-SQL (Microsoft), PL/pgSQL (PostgreSQL), ecc.
Tale procedura è quindi associata ad una tabella e viene automaticamente richiamata dal motore del database quando una certa modifica (o evento) avviene all'interno della tabella. Le modifiche sulla tabella possono includere operazioni INSERT, UPDATE, e DELETE.

## Definizione

La specifica di una regola è generalmente effettuata attraverso il modello ECA (Event-Condition-Action):
L'evento (Event) può essere:
* un'operazione di aggiornamento del database
* un evento sistematico
* un evento esterno
La condizione (Condition), definisce la condizione da verificarsi prima di procedere all'esecuzione della regola. La condizione è facoltativa:
* se non viene specificata, la regola viene eseguita ogni volta che si verifica l'evento.
* se è specificata, la regola viene eseguita solo se la condizione risulta verificata.
L'azione (Action), di solito è una sequenza di comandi SQL e/o di codice scritto con linguaggi di programmazione proprietari (ad esempio PL/SQL nei database Oracle, o Transact-SQL su database Microsoft e Sybase), ma può essere anche una transazione sul database o un programma esterno.
La definizione di un trigger consiste nei seguenti componenti: nome del trigger
    CREATE [OR REPLACE] TRIGGER <nome_trigger>
collocazione temporale del trigger
    BEFORE | AFTER | INSTEAD OF
azione/i del trigger
    INSERT OR UPDATE [OF <colonna(e)>] OR DELETE ON <tabella>
tipo di trigger (opzionale)
    FOR EACH ROW
restrizioni del trigger (solo per trigger for each row)
    WHEN (<condizione>)
corpo del trigger
    <blocco PL/SQL>
La clausola OR REPLACE ri-crea una precedente definizione del trigger qualora questo esista e abbia lo stesso <nome trigger>. Il nome di un trigger può essere scelto arbitrariamente, ma è convenzione comune utilizzare un nome che rifletta la tabella e l'evento(i). Un trigger può essere richiamato prima (BEFORE) o dopo (AFTER) l'evento che causa l'attivazione del trigger. L'evento che causa l'attivazione del trigger specifica prima (o dopo) quale operazione nella tabella <tabella> il trigger debba essere eseguito. Un singolo evento è un inserimento (INSERT), un aggiornamento (UPDATE) o una cancellazione (DELETE); gli eventi possono essere combinati usando la logica or. Se il trigger deve essere eseguito soltanto quando certe colonne vengono aggiornate, queste colonne devono essere specificate dopo l'evento UPDATE.

## Trigger a livello di riga/istruzione

Al fine di programmare i trigger efficientemente (e correttamente), è essenziale capire la differenza tra trigger a livello di riga e trigger a livello di istruzione. Un trigger a livello di riga viene definito utilizzando la clausola FOR EACH ROW. Se questa clausola viene omessa, si assume che il trigger sia a livello di istruzione.

### Esecuzione

Un trigger a livello di riga viene eseguito una volta per ogni riga dopo (o prima) l'evento che lo ha causato. Al contrario, un trigger a livello di istruzione viene eseguito una volta dopo (o prima) dell'evento, indipendentemente da quante righe sono state interessate dall'evento. Per esempio, un trigger di riga con la specifica di evento AFTER UPDATE viene eseguito una volta per ogni riga che viene interessata dall'aggiornamento. Quindi, se l'aggiornamento interessa venti tuple, il trigger viene eseguito venti volte, una volta per ogni riga. Al contrario, un trigger di istruzione viene eseguito una sola volta.

### Caratteristiche dei trigger a livello riga

I trigger di riga hanno alcune speciali caratteristiche che non sono fornite con i trigger di istruzione: solo con un trigger di riga è possibile accedere ai valori degli attributi di una tupla (riga) prima e dopo la modifica, perché il trigger viene eseguito una volta per ogni tupla.
Per un update trigger, si può accedere al vecchio valore di attributo utilizzando:
e si può accedere al nuovo attributo utilizzando
Per un insert trigger, solo
può essere utilizzato, e per un delete trigger solo
è valido (e si riferisce al valore dell'attributo della <colonna> della tupla cancellata). In un trigger di riga quindi è possibile specificare confronti tra il vecchio e il nuovo valore di attributo nel blocco PL/SQL, per esempio:
Se per un trigger di riga il contesto temporale before viene specificato, è anche possibile modificare il nuovo valore della riga, per es.,
Tali modifiche non sono possibili con i trigger di riga after. In generale, è raccomandabile utilizzare un trigger di riga after se la nuova riga non viene modificata nel blocco PL/SQL. I trigger a livello di istruzione sono usati in generale solo in combinazione con il trigger after.

## Clausola when

In una definizione di trigger la clausola WHEN può essere usata solo in combinazione con un trigger FOR EACH ROW. La clausola è utilizzata per restringere ulteriormente l'attivazione del trigger. Per la specifica della condizione nella clausola WHEN, vengono mantenute le stesse restrizioni della clausola CHECK. Le uniche eccezioni sono che le funzioni sysdate e user possono essere utilizzate, e che è possibile far riferimento ai vecchi/nuovi valori degli attributi della riga attuale. In quest'ultimo caso, i due punti “:” non devono essere utilizzati, per esempio solo:
e

## Corpo del trigger

Il corpo del trigger consiste in un blocco PL/SQL. Tutti i comandi SQL e PL/SQL eccetto le due istruzioni COMMIT e ROLLBACK possono essere utilizzati in un blocco PL/SQL di un trigger. Inoltre, costrutti addizionali IF permettono l'esecuzione di certe parti del blocco PL/SQL a seconda dell'evento che aziona il trigger. A questo scopo esistono tre costrutti: IF INSERTING, IF UPDATING, e IF DELETING. Possono essere utilizzati come mostrato nel seguente esempio:
È importante comprendere che l'esecuzione di un blocco PL/SQL di un trigger costituisce una parte di transazione che può contenere eventi che provocano l'attivazione di altri trigger. Quindi, per esempio, un'istruzione INSERT in un blocco PL/SQL può causare l'attivazione di un altro trigger. Più trigger e modifiche quindi possono innescare un'esecuzione a cascata di trigger. Una tale sequenza di trigger termina con successo se
* nessuna eccezione viene rilevata all'interno del blocco PL/SQL, e
* nessuna dichiarazione di vincolo di integrità è stata violata.
Se un trigger rileva un'eccezione in un blocco PL/SQL, tutte le modifiche fino all'inizio della transazione vengono annullate (rollback). Nel blocco PL/SQL di un trigger, un'eccezione può essere provocata utilizzando l'istruzione raise_application_error. Questa istruzione provoca un rollback implicito. In combinazione con un trigger di riga, raise_application_error può far riferimento a vecchi/nuovi valori della riga modificata:
oppure