Documentazione di PostgreSQL 9.0 > Programmazione del server > Trigger
PrecedenteUsare C++ per l'estendibilitàVisibilità del cambiamento dei datiSuccessivo

36. Trigger

Questo capitolo fornisce informazioni generali sulla scrittura di funzioni trigger. Le funzioni trigger possono essere scritte nella maggior parte dei linguaggi procedurali, inclusi PL/pgSQL (Capitolo 39, PL/pgSQL - Linguaggio procedurale SQL), PL/Tcl (Capitolo 40, PL/Tcl - Tcl Procedural Language), PL/Perl (Capitolo 41, PL/Perl - Perl Procedural Language), e PL/Python (Capitolo 42, PL/Python - linguaggio procedurale python). Dopo aver letto questo capitolo, si dovrebbe consultare il capitolo riguardante il linguaggio procedurale preferito per scoprire i dettagli specifici del linguaggio e come usarlo per scrivere un trigger.

È anche possibile scrivere una funzione trigger in C, sebbene la maggior parte delle persone trova più semplice usare uno dei linguaggi procedurali. Attualmente non è possibile scrivere una funzione trigger utilizzando il linguaggio funzionale SQL.

36.1. Panoramica del comportamento dei trigger

Un trigger è una specifica che indica che il database dovrebbe eseguire automaticamente una funzione particolare ogni volte che un certo tipo di operazione viene svolta. I trigger possono essere definiti per essere eseguiti sia prima che dopo qualsiasi operazione INSERT, UPDATE, o DELETE, sia una volta per ogni riga modificata, sia una volta per ogni funzione SQL. I trigger UPDATE possono inoltre essere impostati per attivarsi solo se certe colonne sono menzionate nella clausola SET dell'istruzione UPDATE. I trigger possono anche attivarsi per istruzioni TRUNCATE. Se si manifesta un evento trigger, la funzione trigger viene chiamata nel momento opportuno per gestire l'evento.

La funzione trigger deve essere definita prima che il trigger stesso possa essere creato. La funzione trigger dev'essere dichiarata come una funzione che non prende argomenti e che restituisce il tipo trigger. (La funzione trigger riceve il suo input attraverso una struttura TriggerData passata in modo speciale, non nella forma degli argomenti normali di funzione).

Una volte che una funzione trigger adatta è stata creata, il trigger è definito con CREATE TRIGGER(7). La stessa funzione trigger può essere usata per molteplici trigger.

PostgreSQL™ offre sia trigger per-riga che trigger per-istruzione. Con un trigger per-riga, la funzione trigger viene invocata una volta per ogni riga che è coinvolta dall'istruzione che ha lanciato il trigger. Al contrario, un trigger per-istruzione viene invocato solo una volta quando un'istruzione adatta viene eseguita, a prescindere dal numero di righe coinvolte dall'istruzione. In particolare, un'istruzione che coinvolge zero righe risulterà comunque nell'esecuzione di qualsiasi trigger per-istruzione applicabile. Questi due tipi di tipi di trigger a volte vengono chiamati rispettivamente trigger a livello di riga e trigger a livello di funzione. I trigger sul TRUNCATE possono essere definiti solo a livello di istruzione.

I trigger vengono classificati anche come trigger before e trigger after. I trigger before a livello di istruzione naturalmente si attivano prima che l'istruzione cominci a fare qualsiasi cosa, mentre i trigger after a livello di istruzione si attivano alla reale fine dell'istruzione. I trigger before a livello di riga si attivano immediatamente prima si operi su una riga, mentre i trigger after a livello di riga si attivano alla fine dell'istruzione (ma prima di qualsiasi trigger after a livello di istruzione).

Le funzioni trigger invocate dai trigger per instruzione dovrebbero sempre ritornare NULL. Le funzioni trigger invocate da trigger per riga possono ritornare una riga di tabella (un valore di tipo HeapTuple), se vogliono. Un trigger a livello di riga attivato prima di un'operazione ha le seguenti possibilità:

  • Può ritornare NULL per saltare l'operazione per la riga corrente. Questo istruisce l'esecutore a non svolgere l'operazione a livello di riga che ha invocato il trigger (l'inserimento o la modifica di una particolare riga di tabella).

  • Solo per trigger INSERT e UPDATE a livello di riga, la riga ritornata diventa la riga che sarà inserita o rimpiazzerà la riga che è stata aggiornata. Questo permette che la funzione trigger modifichi la riga che è stata inserita o aggiornata.

Un trigger before a livello di riga che non intende causare nessuno di questi comportamenti deve far attenzione a restituire come suo risultato la stessa riga che gli è stata passata (cioè, la riga NEW per i trigger INSERT e UPDATE, la riga OLD per i trigger DELETE).

Il valore di ritorno viene ignorato per trigger a livello di riga attivati dopo un operazione, e quindi possono ritornare NULL.

Se è definito più di un trigger per lo stesso evento sulla stessa relazione, i trigger saranno attivati in ordine alfabetico per nome del trigger. Nel caso di trigger before, la riga restituita possibilmente-modificata da ogni trigger diventa l'input del prossimo trigger. Se qualunque dei trigger before ritorna NULL, l'operazione viene abbandonata per quella riga e i trigger successivi non vengono attivati.

La definizione di un trigger può anche specificare una condizione booleana WHEN, che sarà testata per vedere se il trigger dovrebbe essere attivato. Nei trigger a livello di riga la condizione WHEN può esaminare i valori vecchi e/o nuovi delle colonne della riga. (I trigger a livello di istruzione possono anche avere condizioni WHEN, anche se la caratteristica non gli è utile). In un trigger before, la condizione WHEN viene valutata appena prima che la funzione venga o verrebbe eseguita, per questo usare WHEN in pratica non è differente da testare la stessa condizione all'inizio della funzione trigger. Comunque, in un trigger after, la condizione WHEN viene valutata appena dopo che avvenga l'aggiornamento della riga, e determina se un evento viene messo in coda per attivare il trigger alla fine dell'istruzione. Per questo quando la condizione WHEN del trigger non ritorna true, non è necessario mettere in coda un evento e nemmeno ri-ottenere la riga alla fine dell'istruzione. Questo può risultare in significative velocizzazioni di instruzioni che modificano molte righe, se il trigger necessita di essere attivato solo per poche righe.

Tipicamente, i trigger before a livello di riga sono usati per controllare o modificare i dati che saranno inseriti o aggiornati. Per esempio, un trigger before potrebbe essere usato per inserire l'orario corrente in una colonna timestamp, o per controllare che due elementi della riga siano consistenti. I trigger after a livello di riga sono i più usati per propagare gli aggiornamenti ad altre tabelle, o per fare controlli di consistenza rispetto ad altre tabelle. La ragione per questa divisione del lavoro è che un trigger after può essere certo che sta vedendo il valore finale della riga, mentre un trigger before non può; ci potrebbero essere altri trigger before che si attivano dopo. Se non si hanno ragioni specifiche per realizzare un trigger befor o after, la modalità before è più efficiente, dato che l'informazione sull'operazione non deve essere salvata fino alla fine dell'istruzione.

Se una funzione trigger esegue comandi SQL allora questi comandi potrebbero attivare altri trigger. Questi sono conosciuti come trigger in cascata. Non c'è una limitazione diretta sul numero di livelli in cascata. È possibile causare un'invocazione ricorsiva dello stesso trigger; per esempio, un trigger INSERT potrebbe eseguire un comando che inserisce una riga addizionale nella stessa tabella, causando l'ulteriore attivazione del trigger INSERT. È responsabilità del programmatore di trigger escludere le ricursioni infinite in tali scenari.

Quando si definisce un trigger, gli si possono specificare degli argomenti. Lo scopo di includere argomenti nella definizione del trigger è di permette che trigger diversi con requisiti simili chiamino la stessa funzione. Come esempio, ci potrebbe essere una funzione trigger generalizzata che prende come argomenti due nomi di colonna e mette l'utente corrente in una e il timestap corrente nell'altra. Se scritta correttamente, questa funzione trigger sarà indipendente della specifica tabella su cui sta "triggerando". Per questo la stessa funzione potrebbe essere usata per eventi INSERT su ogni tabella con colonne adatte, per esempio per tenere traccia automaticamente della creazione di record in una tabella di transazione. Può essere anche usata per tenere traccia degli eventi aggiornati per ultimi se definito come trigger UPDATE.

Ogni linguaggio di programmazione che supporta i trigger ha i propri metodi per rendere i dati in input al trigger disponibili alla funzione trigger. Questi dati in input includono il tipo dell'evento trigger (per es., INSERT o UPDATE) così come qualsiasi argomento elencato in CREATE TRIGGER. Per un trigger a livello di riga, i dati in input includono anche la riga NEW per trigger INSERT e UPDATE, e/o la riga OLD per trigger UPDATE e DELETE. I trigger a livello di istruzione non hanno attualmente nessuna possibilità di esaminare la riga/e individuale modificata dall'istruzione.

Documentazione di PostgreSQL 9.0 > Programmazione del server > Trigger
PrecedenteUsare C++ per l'estendibilitàVisibilità del cambiamento dei datiSuccessivo