Tre problemi, tre momenti di azione
Un vincolo chiede: questa linea rispetta sempre una regola? Un transaction chiede: queste operazioni dovrebbero avere successo o fallire insieme? Un trigger chiede: dovremmo reagire automaticamente quando si verifica un evento relativo ai dati?
La scelta giusta inizia da questa differenza. Utilizza un trigger per tutte le regole della cache; l'utilizzo solo dell'applicazione consente a ciascun processo di reimplementare i controlli.
Vincolo: impedisce uno stato non valido
NOT NULL richiede un valore, UNIQUE evita una ripetizione, CHECK controlla una condizione e FOREIGN KEY garantisce l'esistenza di una relazione. Queste regole sono dichiarative e visibili nella struttura.
Per evitare un prezzo negativo, il CHECK è preferibile al trigger: la regola è breve, atomica e compresa direttamente dallo DBMS.
CREATE TABLE produits (
id_produit INTEGER PRIMARY KEY,
prix NUMERIC NOT NULL CHECK (prix >= 0)
);Transaction: proteggere un'operazione composta
Un ordine e il relativo pagamento riguardano due tabelle, ma costituiscono un'unica intenzione commerciale. BEGIN apre transaction, COMMIT conferma e ROLLBACK annulla. SAVEPOINT offre un rendimento parziale in uno transaction più lungo.
Uno transaction non sostituisce i vincoli: garantisce l'atomicità delle operazioni, mentre i vincoli controllano ogni stato proposto.
BEGIN;
INSERT INTO commandes (id_commande, montant) VALUES (108, 120);
INSERT INTO paiements (id_commande, montant) VALUES (108, 120);
-- COMMIT se tutto riesce, altrimenti ROLLBACK
COMMIT;Trigger: reagire a un evento
PostgreSQL separa la funzione di trigger e il trigger collegato al tavolo. OLD contiene la riga prima della modifica, NEW la riga proposta. DOPO UPDATE è adatto per una cronologia delle modifiche già accettata.
PRIMA può modificare o rifiutare NUOVO, ma un vincolo rimane più chiaro per una regola semplice. ROW esegue la funzione per ogni riga; STATEMENT lo esegue una volta per l'istruzione.
CREATE FUNCTION journaliser_prix() RETURNS trigger AS $$
BEGIN
INSERT INTO historique_prix (id_produit, ancien_prix, nouveau_prix)
VALUES (OLD.id_produit, OLD.prix, NEW.prix);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER audit_prix
AFTER UPDATE OF prix ON produits
FOR EACH ROW EXECUTE FUNCTION journaliser_prix();Quando non utilizzare un trigger
Un trigger è particolarmente adatto per un controllo o un logging che deve essere applicato indipendentemente dal chiamante. Anche in questo caso, documentate l’effetto, verificate gli errori e misurate il costo.
- Un vincolo esprime direttamente la regola semplice.
- La logica deve essere visibile in un servizio applicativo e con esso la versione.
- Una modifica massiccia comporterebbe un'elaborazione costosa per riga.
- Il trigger rischia di modificare la stessa tabella e creare una ricorsione.
- Al team mancano i test e la supervisione necessari.
Guida rapida alla scelta
Per prima cosa chiedi se stai proteggendo una riga, un insieme di operazioni o una reazione a un evento. Combina gli strumenti quando le loro responsabilità differiscono: CHECK rifiuta un prezzo non valido, uno transaction raggruppa la modifica e il suo pagamento, un trigger mantiene il vecchio prezzo accettato.
Non scegliere la lunghezza del codice. Scegli regola aziendale, visibilità, tempo di esecuzione, comportamento degli errori e costi sotto carico.
Dipende da te
Combina questi casi: singola email, bonifico di addebito/credito, cronologia indirizzi, ordine collegato a un cliente e creazione di ordine/pagamento. Le risposte attese sono rispettivamente vincolo, transaction, possibile trigger, chiave esterna e transaction.
La micro-formazione avanzata rimane in preparazione fino a quando un laboratorio PostgreSQL modificabile e ripristinabile non avrà superato i test di sicurezza e robustezza.
Segui la preparazione di questa competenza.
Consulta il risultato previsto, i prerequisiti e lo stato reale del micro-corso.
