DELETE CASCADE SQL postgres ou triggers personnalisés : que choisir ?

DELETE CASCADE en PostgreSQL et les triggers personnalisés répondent au même besoin : propager une suppression vers les tables dépendantes sans laisser d’enregistrements orphelins. Mais ces deux approches ne couvrent pas les mêmes situations, et choisir la mauvaise peut coûter cher, soit en perte de données silencieuse, soit en dette de maintenance.

Ce que DELETE CASCADE fait réellement dans PostgreSQL

On déclare ON DELETE CASCADE directement sur la contrainte de clé étrangère. Quand une ligne parent est supprimée, PostgreSQL propage automatiquement la suppression vers toutes les lignes enfants qui la référencent, avant même que la transaction ne soit validée.

La syntaxe est simple :

ALTER TABLE commandes ADD CONSTRAINT fk_client FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE;

À partir de là, supprimer un client supprime toutes ses commandes. Pas de code applicatif, pas de logique supplémentaire.

Deux points techniques méritent attention. D’abord, les index sur les colonnes de clé étrangère côté enfant sont nécessaires : sans eux, PostgreSQL parcourt toute la table enfant pour chaque suppression parent, ce qui devient coûteux dès que les volumes augmentent. Ensuite, si on enchaîne plusieurs niveaux de cascade (commandes → lignes de commande → détails de livraison), chaque niveau déclenche ses propres vérifications référentielles, ce qui multiplie le travail du moteur.

NO ACTION vs RESTRICT : la distinction que PostgreSQL change tout

Les concurrents traitent ces deux options comme équivalentes. Elles ne le sont pas dans PostgreSQL.

Avec NO ACTION, la vérification de la contrainte peut être différée à la fin de la transaction si la contrainte est déclarée DEFERRABLE. Cela permet, dans une seule transaction, de réorganiser des lignes parentes avant de vérifier que toutes les références sont cohérentes. Avec RESTRICT, la vérification est immédiate : impossible de supprimer la ligne parent si des enfants existent, même si on les supprime dans la même transaction quelques instructions plus tard.

Ce détail oriente directement le choix dans les migrations ou les réorganisations de données où l’ordre des opérations n’est pas trivial.

Architecte base de données comparant triggers SQL personnalisés et DELETE CASCADE sur laptop avec notes manuscrites

Triggers personnalisés : quand la cascade déclarative ne suffit pas

Prenons un cas concret : on supprime un compte utilisateur, mais on veut archiver ses commandes dans une table d’audit plutôt que les effacer, et envoyer une notification à un service externe. ON DELETE CASCADE ne peut pas faire ça. Un trigger le peut.

Un trigger BEFORE DELETE ou AFTER DELETE sur la table parent permet d’exécuter n’importe quelle logique PL/pgSQL : copier des lignes vers une table d’archive, mettre à jour des compteurs dénormalisés, appeler des fonctions qui écrivent dans des queues de messages.

Quelques situations où un trigger s’impose :

  • Suppression logique (soft delete) : on ne supprime pas physiquement les lignes enfants, on les marque comme inactives via un champ deleted_at. CASCADE détruirait les données ; le trigger les conserve.
  • Archivage avant suppression : on insère les lignes dans une table d’historique avant de les effacer, pour garder une trace exploitable.
  • Propagation conditionnelle : certaines lignes enfants doivent être supprimées, d’autres réaffectées à une entité par défaut selon leur statut. Cette logique n’entre pas dans une contrainte déclarative.
  • Effacements en lots : sur de grandes tables, supprimer des milliers de lignes en une seule opération peut verrouiller la table trop longtemps. Un trigger peut orchestrer des suppressions par batch pour limiter la contention.

Le problème de la réplication logique PostgreSQL avec les cascades

C’est un angle rarement mentionné. Quand on utilise la réplication logique entre un serveur source et un abonné, les suppressions en cascade ne sont pas garanties de se propager correctement si la table enfant n’est pas répliquée sur l’abonné.

PostgreSQL transmet les événements de suppression ligne par ligne tels qu’ils se produisent sur le serveur source. Si une table enfant existe uniquement côté abonné, elle n’est pas touchée par la cascade. Il faut alors prévoir un nettoyage explicite côté abonné, ou s’assurer que la chaîne de dépendances entière est couverte par la réplication.

Les triggers ordinaires posent un problème symétrique : le worker de réplication qui applique les changements peut ne pas les exécuter. Il faut vérifier la configuration session_replication_role si on compte sur des triggers pour maintenir la cohérence des données répliquées.

Critères de choix entre DELETE CASCADE et trigger PostgreSQL

La règle pratique : ON DELETE CASCADE quand la suppression doit être totale, immédiate et sans condition. Un trigger quand il faut de la logique, de l’archivage, ou une granularité que la contrainte déclarative ne permet pas d’exprimer.

Quelques repères concrets :

  • Tables de logs ou de sessions liées à un utilisateur : CASCADE est adapté. Ces données n’ont pas de valeur autonome une fois le parent disparu.
  • Entités métier (commandes, contrats, factures) : préférer un trigger ou une suppression applicative explicite. Une suppression silencieuse sur ces tables peut être catastrophique et difficile à tracer.
  • Chaînes de dépendances profondes : tester l’impact avant de déployer. Une cascade sur trois niveaux avec des tables volumineuses peut dégrader les performances de façon inattendue si les index de clé étrangère manquent.
  • Environnements avec réplication logique : auditer quelle partie du schéma est répliquée avant de s’appuyer sur CASCADE ou sur des triggers pour la cohérence des données.

Les deux mécanismes peuvent coexister. On peut déclarer CASCADE pour les tables techniques (sessions, tokens, logs) et maintenir des triggers sur les tables métier. Ce n’est pas une opposition binaire.

Le piège le plus fréquent reste l’absence d’index sur la colonne de clé étrangère côté table enfant : CASCADE fonctionne correctement, mais chaque suppression parent déclenche un scan séquentiel. Sur une table de plusieurs millions de lignes, l’impact se mesure en secondes par opération.

Articles populaires

A PROPOS DU BLOG

Blog du Marketing

Le Blog du Marketing est un site internet, ouvert aux contributions, consacré aux infos et conseils autour du marketing, du webmarketing, mais aussi du secteur de la communication en général.

Il vous sera possible de vous informer sur de nombreux sujets autour de ce secteur, via des articles de nos rédacteurs, que cela soit par exemple à propos du référencement naturel / SEO et du SEM, les audits marketing et études de satisfaction ainsi que sur les stratégies de marketing digital …