Guide complet sur la suppression en cascade
L'article pilier – approfondissement de l'option ON DELETE CASCADE.
Maîtrisez les clés étrangères : syntaxe, options ON DELETE et ON UPDATE, cas d'usage, bonnes pratiques et pièges à éviter en MySQL, PostgreSQL et SQL Server.
Une clé étrangère (ou foreign key) est une contrainte qui établit un lien entre deux tables. Elle garantit que les valeurs d'une colonne (ou d'un groupe de colonnes) dans une table enfant correspondent à des valeurs existantes dans une table parent.
Dans une base de données e-commerce, la table commandes a une colonne client_id qui fait référence à clients(id). La foreign key garantit qu'on ne peut pas créer une commande pour un client qui n'existe pas.

Diagramme des relations entre tables parent et enfant (assisté par Nano Banana 2)
La foreign key empêche les enregistrements orphelins (enfants sans parent). C'est la base des bases de données relationnelles.
Avec ON DELETE CASCADE ou ON UPDATE CASCADE, les modifications se propagent automatiquement.
Les foreign keys documentent directement dans la base les relations entre tables. Tout développeur qui arrive sur le projet comprend immédiatement les liens.
Les SGBD créent automatiquement des index sur les colonnes de foreign key, accélérant les jointures (JOIN).
CREATE TABLE commandes (
id INT PRIMARY KEY,
client_id INT REFERENCES clients(id)
);
CREATE TABLE commandes (
id INT PRIMARY KEY,
client_id INT,
CONSTRAINT fk_commandes_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
CREATE TABLE lignes_commande (
commande_id INT,
produit_id INT,
quantite INT,
PRIMARY KEY (commande_id, produit_id),
FOREIGN KEY (commande_id) REFERENCES commandes(id),
FOREIGN KEY (produit_id) REFERENCES produits(id)
);
| Option | DELETE (suppression parent) | UPDATE (modification clé parent) |
|---|---|---|
| CASCADE | Supprime les enfants自动 | Met à jour les clés étrangères enfants |
| RESTRICT (par défaut sur plusieurs SGBD) | Bloque la suppression si des enfants existent | Bloque la modification si des enfants existent |
| NO ACTION | Similaire à RESTRICT (timing différé) | Similaire à RESTRICT |
| SET NULL | Met la foreign key à NULL | Met la foreign key à NULL |
| SET DEFAULT | Met la valeur par défaut | Met la valeur par défaut |

Infographie des options avec cas d'usage (assisté par Nano Banana 2)
-- Table parent
CREATE TABLE clients (
id INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE
) ENGINE=InnoDB;
-- Table enfant avec foreign key
CREATE TABLE commandes (
id INT PRIMARY KEY AUTO_INCREMENT,
client_id INT,
montant DECIMAL(10,2),
date_commande DATE,
CONSTRAINT fk_commandes_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE RESTRICT
ON UPDATE CASCADE
) ENGINE=InnoDB;
-- Vérifier les foreign keys existantes
SHOW CREATE TABLE commandes;
SELECT * FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'clients';
-- Table parent
CREATE TABLE clients (
id SERIAL PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE
);
-- Table enfant (syntaxe simplifiée)
CREATE TABLE commandes (
id SERIAL PRIMARY KEY,
client_id INT REFERENCES clients(id) ON DELETE SET NULL,
montant DECIMAL(10,2),
date_commande DATE
);
-- Alternative avec contrainte nommée
CREATE TABLE commandes (
id SERIAL PRIMARY KEY,
client_id INT,
montant DECIMAL(10,2),
date_commande DATE,
CONSTRAINT fk_commandes_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE SET NULL
);
-- Lister les foreign keys
SELECT conname, conrelid::regclass AS table_name
FROM pg_constraint
WHERE contype = 'f';
-- Table parent
CREATE TABLE clients (
id INT IDENTITY PRIMARY KEY,
nom NVARCHAR(100) NOT NULL,
email NVARCHAR(100) UNIQUE
);
-- Table enfant avec foreign key
CREATE TABLE commandes (
id INT IDENTITY PRIMARY KEY,
client_id INT,
montant DECIMAL(10,2),
date_commande DATE,
CONSTRAINT fk_commandes_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE NO ACTION -- équivalent à RESTRICT
);
-- Désactiver temporairement une foreign key (rare !)
ALTER TABLE commandes NOCHECK CONSTRAINT fk_commandes_client;
-- Réactiver
ALTER TABLE commandes CHECK CONSTRAINT fk_commandes_client;
-- MySQL
ALTER TABLE commandes DROP FOREIGN KEY fk_commandes_client;
-- PostgreSQL / SQL Server
ALTER TABLE commandes DROP CONSTRAINT fk_commandes_client;
-- Tous SGBD
ALTER TABLE commandes
ADD CONSTRAINT fk_commandes_client
FOREIGN KEY (client_id)
REFERENCES clients(id)
ON DELETE CASCADE;
fk_table_parent_table_enfant facilite la maintenance.BEGIN; DELETE ...; ROLLBACK; pour tester sans risque.fk_[table_enfant]_[table_parent] ou fk_[table_enfant]_[colonne]
Exemple : fk_commandes_clients ou fk_commandes_client_id
Cause : Moteur MyISAM (non supporté) ou types de colonnes incompatibles.
Solution : Utilisez ENGINE=InnoDB et vérifiez que les types correspondent (ex: INT vs BIGINT).
Cause : ON DELETE RESTRICT et des enfants existent.
Solution : Supprimez d'abord les enfants ou modifiez la contrainte en CASCADE.
Cause : Des lignes enfants pointent vers des parents inexistants.
Solution : Nettoyez d'abord : DELETE FROM enfants WHERE parent_id NOT IN (SELECT id FROM parents);
Cause : Chaque insertion vérifie la présence du parent (coût normal).
Solution : Acceptez ce coût (c'est le prix de l'intégrité) ou désactivez temporairement les FK pour des imports massifs (dangereux).
Oui, sans limite théorique. Une table lignes_commande peut avoir une FK vers commandes et une autre vers produits. Chaque FK est indépendante.
Oui, c'est utile pour les structures hiérarchiques (ex: table employes avec manager_id référençant employes(id)). Attention aux suppressions en cascade qui peuvent supprimer tout un arbre.
Oui, pour les performances des jointures et des vérifications d'intégrité. MySQL et PostgreSQL créent automatiquement un index sur les colonnes FK. SQL Server ne le fait pas automatiquement pour les contraintes (sauf si c'est aussi une clé primaire).
C'est rarement une bonne idée. Pour des imports massifs, on peut désactiver les FK (MySQL : SET FOREIGN_KEY_CHECKS=0;, SQL Server : NOCHECK CONSTRAINT), mais il faut les réactiver et vérifier l'intégrité ensuite. À utiliser avec précaution.
Un index accélère les recherches. Une foreign key est une contrainte d'intégrité. Une FK peut être supportée par un index (c'est même recommandé), mais ce sont deux concepts différents. Une table peut avoir des index sans FK et des FK sans index (déconseillé).
Non, pas nativement. Les bases NoSQL (MongoDB, Cassandra) ne supportent pas les foreign keys. L'intégrité référentielle doit être gérée au niveau applicatif. C'est l'un des principaux compromis quand on choisit NoSQL plutôt qu'une base relationnelle.
Les clés étrangères sont un pilier des bases de données relationnelles. Elles garantissent l'intégrité des données, documentent le schéma et peuvent automatiser certaines opérations via CASCADE.