ON DELETE CASCADE est une option de contrainte de clé étrangère qui demande au moteur de base de données de supprimer automatiquement toutes les lignes enfants dépendantes lorsqu’une ligne parente est supprimée. Sans cette option, une suppression sur la table parente échoue dès qu’une ligne enfant y fait référence, à moins d’avoir vidé manuellement les tables dans le bon ordre.
Clés étrangères et intégrité référentielle : le socle de la cascade
Une clé étrangère relie une colonne d’une table enfant à la clé primaire d’une table parente. Cette contrainte garantit qu’aucune ligne enfant ne peut pointer vers un parent inexistant. C’est ce qu’on appelle l’intégrité référentielle.
Par défaut, les moteurs SQL appliquent la règle la plus restrictive : toute tentative de suppression d’une ligne parente encore référencée est bloquée. ON DELETE CASCADE remplace ce comportement par une propagation automatique de la suppression vers les tables enfants.
Deux autres options existent pour compléter le tableau : ON DELETE SET NULL, qui met la clé étrangère à NULL plutôt que de supprimer la ligne enfant, et ON DELETE RESTRICT, qui interdit explicitement la suppression du parent tant qu’une ligne enfant existe. Choisir entre ces trois options dépend de ce que représente la relation dans le modèle métier.
Syntaxe SQL pour déclarer ON DELETE CASCADE
La contrainte se déclare au moment de la création de la table enfant, dans la clause FOREIGN KEY. Le mot-clé CASCADE suit immédiatement ON DELETE.
Exemple avec une table commandes liée à une table clients :
CREATE TABLE commandes (
id_commande INT PRIMARY KEY,
id_client INT NOT NULL,
FOREIGN KEY (id_client) REFERENCES clients(id_client) ON DELETE CASCADE
);
Lorsqu’un client est supprimé via DELETE FROM clients WHERE id_client = 42, le moteur supprime automatiquement toutes les lignes de commandes dont id_client vaut 42. Aucun DELETE supplémentaire n’est requis sur la table enfant.
Pour ajouter la contrainte sur une table existante, la procédure diffère selon le moteur : sur MySQL et PostgreSQL, il faut d’abord supprimer la contrainte de clé étrangère existante avec ALTER TABLE … DROP FOREIGN KEY (MySQL) ou DROP CONSTRAINT (PostgreSQL), puis la recréer avec l’option CASCADE.
Différences entre MySQL/InnoDB et PostgreSQL
Les deux moteurs supportent ON DELETE CASCADE, mais leur comportement interne diverge sur deux points concrets que les concurrents mentionnent rarement.
Le premier concerne les index sur les colonnes de clé étrangère côté enfant. MySQL/InnoDB crée automatiquement un index sur la colonne référençante si aucun index compatible n’existe. PostgreSQL ne le fait pas. Sans cet index, PostgreSQL doit parcourir séquentiellement la table enfant pour identifier les lignes à supprimer, ce qui peut dégrader fortement les performances sur de grandes tables. Il convient donc de créer manuellement cet index lors de la conception du schéma sous PostgreSQL.
Le second point concerne les triggers DELETE sur les tables enfants. Sous MySQL/InnoDB, les suppressions déclenchées par ON DELETE CASCADE ne firing pas les triggers DELETE définis sur la table enfant. Un trigger d’audit censé tracer chaque suppression ne sera tout simplement pas exécuté pour les lignes supprimées par cascade. Les systèmes qui s’appuient sur des triggers pour alimenter un journal ou un flux de capture de changements (CDC) doivent en tenir compte impérativement.

Concilier ON DELETE CASCADE et les transactions
L’angle que les concurrents n’abordent pas concerne la combinaison de ON DELETE CASCADE avec les transactions explicites. Toutes les suppressions en cascade font partie de la même transaction que le DELETE initial. Si une suppression dans une table enfant ou petits-enfants déclenche une violation (par exemple une contrainte CHECK ou une clé étrangère sans option CASCADE plus loin dans la chaîne), l’ensemble de la transaction est annulé.
Cela a deux conséquences pratiques. Premièrement, la suppression en cascade est atomique : soit toutes les lignes dépendantes sont supprimées, soit aucune ne l’est. Deuxièmement, si la chaîne des clés étrangères comporte une relation sans action compatible déclarée, le moteur rejette la suppression du parent même si ON DELETE CASCADE est déclaré plus haut dans la hiérarchie. Il faut donc examiner toute la chaîne de dépendances avant d’activer une cascade, en particulier dans les schémas comportant plusieurs niveaux de relations.
Envelopper le DELETE dans une transaction explicite permet de vérifier le nombre de lignes supprimées avant de valider :
BEGIN;
DELETE FROM clients WHERE id_client = 42;
— vérifier le résultat avant COMMIT
COMMIT;
En cas de doute, un ROLLBACK annule toutes les suppressions, y compris celles propagées par cascade.
Quand utiliser ON DELETE CASCADE : critères de décision
ON DELETE CASCADE convient lorsque les lignes enfants n’ont pas de sens indépendamment du parent. Les cas d’usage typiques sont :
- Les lignes de commande liées à une commande : supprimer la commande sans ses lignes laisserait des données orphelines sans valeur.
- Les commentaires ou pièces jointes liés à un article de blog : leur existence dépend entièrement de l’article parent.
- Les données de session ou de cache liées à un utilisateur : la suppression du compte doit nettoyer toutes les données associées.
En revanche, ON DELETE CASCADE est à éviter lorsque les données enfants ont une valeur indépendante ou doivent être archivées avant suppression. Une facture liée à un client ne doit pas disparaître si le compte client est fermé : mieux vaut ON DELETE RESTRICT combiné à une procédure d’archivage explicite.
Vérifier les contraintes CASCADE existantes
Avant de modifier un schéma, il est utile de savoir quelles contraintes ON DELETE CASCADE sont déjà déclarées. Sous PostgreSQL, la vue information_schema.referential_constraints expose la colonne delete_rule pour chaque contrainte de clé étrangère. Sous MySQL, la table information_schema.KEY_COLUMN_USAGE combinée à REFERENTIAL_CONSTRAINTS donne la même information.
Identifier toutes les cascades actives dans un schéma évite les suppressions inattendues lors des opérations de maintenance ou de migration. Cette vérification est particulièrement critique lorsqu’on importe un schéma existant dans un nouvel environnement : les contraintes sont portées par la définition des tables, pas par les scripts d’insertion.
ON DELETE CASCADE reste l’un des outils les plus efficaces pour maintenir la cohérence d’une base relationnelle sans multiplier les requêtes applicatives. Sa mise en oeuvre demande simplement une analyse préalable du modèle de données et de la chaîne complète des dépendances entre tables.

