Immagina di sviluppare un'app per gestire studenti e corsi, e hai una tabella students. In questa tabella c'è il campo last_modified, che dovrebbe aggiornarsi in automatico ogni volta che modifichi i dati di una riga (tipo quando cambi il nome dello studente o la sua età).
Invece di scrivere manualmente l'update di last_modified in ogni query SQL, creiamo un trigger che lo fa per noi.
Struttura della tabella students
Per cominciare, creiamo la tabella students che useremo nell'esempio. Questa tabella contiene le info base sugli studenti:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY, -- Identificatore unico dello studente
name VARCHAR(100) NOT NULL, -- Nome dello studente
age INT, -- Età dello studente
last_modified TIMESTAMP NOT NULL DEFAULT NOW() -- Ora dell'ultima modifica
);
- Il campo
last_modifiedviene inizialmente riempito con l'orario attuale (NOW()) quando crei la riga. - Questo campo si aggiornerà in automatico quando cambi i dati dello studente.
Inseriamo qualche dato di test nella tabella:
INSERT INTO students (name, age)
VALUES
('Otto Lin', 20),
('Maria Chi', 22),
('Alex Song', 19);
Ora i dati nella tabella sono così:
| student_id | name | age | last_modified |
|---|---|---|---|
| 1 | Otto Lin | 20 | 2023-10-15 12:00:00 |
| 2 | Maria Chi | 22 | 2023-10-15 12:00:00 |
| 3 | Alex Song | 19 | 2023-10-15 12:00:00 |
Creazione della funzione per aggiornare last_modified
La funzione in PL/pgSQL verrà usata dal trigger per aggiornare il valore del campo last_modified. Verrà chiamata in automatico prima che una riga venga modificata.
Creiamo la funzione update_last_modified:
CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
-- Aggiorniamo il campo last_modified con l'orario attuale
NEW.last_modified := NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
NEW— è una variabile speciale che contiene i nuovi dati della riga (dopo la modifica).- Impostiamo
NEW.last_modifiedaNOW()(data e ora attuali). - La funzione restituisce la variabile aggiornata
NEW, che serve per far funzionare il trigger.
Creazione del trigger
Ora creiamo il trigger che chiamerà in automatico la funzione update_last_modified ogni volta che aggiorni una riga nella tabella students.
CREATE TRIGGER set_last_modified
BEFORE UPDATE ON students
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();
Cosa succede qui:
BEFORE UPDATEindica che il trigger parte prima dell'operazione di update.FOR EACH ROWvuol dire che il trigger scatta per ogni riga modificata.EXECUTE FUNCTION update_last_modified()dice di chiamare la funzioneupdate_last_modified.
Test del trigger
Vediamo ora come funziona il nostro trigger. Selezioniamo i dati attuali dalla tabella students:
SELECT * FROM students;
Risultato:
| student_id | name | age | last_modified |
|---|---|---|---|
| 1 | Otto Lin | 20 | 2023-10-15 12:00:00 |
| 2 | Maria Chi | 22 | 2023-10-15 12:00:00 |
| 3 | Alex Song | 19 | 2023-10-15 12:00:00 |
Ora aggiorniamo l'età dello studente con student_id = 1:
UPDATE students
SET age = 21
WHERE student_id = 1;
Selezioniamo di nuovo i dati dalla tabella:
SELECT * FROM students;
Risultato atteso:
| student_id | name | age | last_modified |
|---|---|---|---|
| 1 | Otto Lin | 21 | 2023-10-15 14:00:00 |
| 2 | Maria Chi | 22 | 2023-10-15 12:00:00 |
| 3 | Alex Song | 19 | 2023-10-15 12:00:00 |
Nota: il campo last_modified per la riga con student_id = 1 è stato aggiornato all'orario attuale, mentre le altre righe sono rimaste uguali.
Estendere la logica del trigger
Supponiamo ora di voler aggiornare il campo last_modified solo se vengono modificati certi campi. Per esempio, se cambia solo il nome dello studente o la sua età, il trigger deve scattare, ma per altri cambiamenti no.
Per questo puoi aggiungere una condizione con l'operatore WHEN nella definizione del trigger.
Creiamo un nuovo trigger con condizione:
DROP TRIGGER IF EXISTS set_last_modified ON students;
CREATE TRIGGER set_last_modified
BEFORE UPDATE ON students
FOR EACH ROW
WHEN (OLD.name IS DISTINCT FROM NEW.name OR OLD.age IS DISTINCT FROM NEW.age)
EXECUTE FUNCTION update_last_modified();
Qui:
- La condizione
WHENcontrolla se i vecchi valori (OLD) sono diversi dai nuovi (NEW) per i campinameeage. - Se nessuno di questi campi è cambiato, il trigger non parte.
Proviamo di nuovo ad aggiornare i dati nella tabella e testiamo la nuova logica.
Consigli sull'uso dei trigger
- Non abusare dei trigger. Sono comodi, ma possono complicare la logica del database e rendere il debug più difficile.
- Documenta sempre cosa fa un trigger e in quali casi viene usato.
- Usa le condizioni
WHENper minimizzare chiamate involontarie del trigger. - Ricorda che i trigger possono influire sulle performance del database, soprattutto se la tabella ha tante righe.
Errori tipici con i trigger
Modifica sbagliata dei dati. Per esempio, ti dimentichi di impostare il valore per NEW e restituisci i dati originali senza cambiamenti.
Condizioni sbagliate. Tipo, ti dimentichi di aggiungere la condizione WHEN e il trigger scatta anche quando non serve.
Ricorsione. Se il trigger chiama una funzione che a sua volta richiama il trigger, rischi di creare un ciclo infinito. PostgreSQL ha una protezione contro la ricorsione, ma meglio evitare queste situazioni.
Questo esempio mostra come i trigger possono semplificare l'aggiornamento automatico dei dati. Nei progetti reali questa tecnica si usa spesso per tracciare le modifiche, mantenere l'integrità dei dati e automatizzare lavori noiosi.
GO TO FULL VERSION