PostgreSQL

Contraintes, transactions ou triggers : quel outil choisir ?

Ces trois outils protègent les données à des moments différents. Les confondre ajoute de la complexité sans améliorer la fiabilité.

Équipe SQL.tn10 min
Une barrière refuse une valeur invalide, une capsule sécurise deux opérations et un capteur archive un changement

Trois problèmes, trois moments d’action

Une contrainte demande : cette ligne respecte-t-elle toujours une règle ? Une transaction demande : ces opérations doivent-elles réussir ou échouer ensemble ? Un trigger demande : faut-il réagir automatiquement lorsqu’un événement de données survient ?

Le bon choix commence par cette différence. Utiliser un trigger pour tout cache des règles ; utiliser seulement l’application laisse chaque processus réimplémenter les contrôles.

Contrainte : empêcher un état invalide

NOT NULL exige une valeur, UNIQUE évite une répétition, CHECK vérifie une condition et FOREIGN KEY garantit l’existence d’une relation. Ces règles sont déclaratives et visibles dans la structure.

Pour empêcher un prix négatif, CHECK est préférable à un trigger : la règle est courte, atomique et comprise directement par le SGBD.

Contrainte PostgreSQL vérifiée
CREATE TABLE produits (
  id_produit INTEGER PRIMARY KEY,
  prix NUMERIC NOT NULL CHECK (prix >= 0)
);

Transaction : protéger une opération composée

Une commande et son paiement concernent deux tables, mais forment une seule intention métier. BEGIN ouvre la transaction, COMMIT confirme et ROLLBACK annule. SAVEPOINT offre un retour partiel dans une transaction plus longue.

Une transaction ne remplace pas les contraintes : elle garantit l’atomicité des opérations, tandis que les contraintes vérifient chaque état proposé.

Annuler si le paiement échoue
BEGIN;
INSERT INTO commandes (id_commande, montant) VALUES (108, 120);
INSERT INTO paiements (id_commande, montant) VALUES (108, 120);
-- COMMIT si tout réussit, sinon ROLLBACK
COMMIT;

Trigger : réagir à un événement

PostgreSQL sépare la fonction de trigger et le trigger attaché à la table. OLD contient la ligne avant modification, NEW la ligne proposée. AFTER UPDATE convient à un historique du changement déjà accepté.

BEFORE peut modifier ou refuser NEW, mais une contrainte reste plus claire pour une règle simple. ROW exécute la fonction pour chaque ligne ; STATEMENT l’exécute une fois pour l’instruction.

Historiser un prix avec PostgreSQL
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();

Quand ne pas utiliser un trigger

Un trigger convient particulièrement à un audit ou une historisation qui doit s’appliquer quel que soit l’appelant. Même dans ce cas, documentez l’effet, testez les erreurs et mesurez le coût.

  • Une contrainte exprime directement la règle simple.
  • La logique doit être visible dans un service applicatif et versionnée avec lui.
  • Une modification massive déclencherait un traitement coûteux par ligne.
  • Le trigger risque de modifier la même table et de créer une récursion.
  • L’équipe ne dispose pas des tests et de la supervision nécessaires.

Guide de choix rapide

Demandez d’abord si vous protégez une ligne, un ensemble d’opérations ou une réaction à un événement. Combinez les outils lorsque leurs responsabilités diffèrent : CHECK refuse un prix invalide, une transaction regroupe la modification et son paiement, un trigger conserve l’ancien prix accepté.

Ne choisissez pas sur la longueur du code. Choisissez sur la règle métier, la visibilité, le moment d’exécution, le comportement en erreur et le coût sous charge.

Contrainte = état valide. Transaction = tout ou rien. Trigger = réaction automatique à un événement.

À vous de décider

Associez ces cas : e-mail unique, virement débit/crédit, historique d’une adresse, commande liée à un client et création commande/paiement. Les réponses attendues sont respectivement contrainte, transaction, trigger éventuel, clé étrangère et transaction.

Les micro-formations avancées restent en préparation tant qu’un laboratoire PostgreSQL modifiable et réinitialisable n’a pas passé ses tests de sécurité et de robustesse.

Suivez la préparation de cette compétence.

Consultez le résultat visé, les prérequis et le statut réel de la micro-formation.

Voir la micro-formation
Contraintes, transactions ou triggers : guide de choix — SQL.tn