Imagine que t'as créé une base de données avec une table de clients (customers) et des commandes (orders) qui leur sont liées. Mais à un moment, tu te demandes : qu'est-ce qui se passe si tu supprimes un client de la table customers ? Est-ce que ses commandes doivent aussi être supprimées, ou elles vont rester "orphelines", pointant vers un client qui n'existe plus ? Et si tu veux changer l'ID du client ? C'est là que les opérations en cascade (CASCADE) et les restrictions (RESTRICT) entrent en jeu pour gérer le comportement de la base.
ON DELETE CASCADE — c'est un mécanisme qui supprime automatiquement les enregistrements liés quand tu supprimes une ligne de la table parente. En gros, si tu supprimes un client, toutes ses commandes partent avec lui.
Voilà comment ça marche. Quand tu ajoutes ON DELETE CASCADE à la définition de la clé étrangère, la base "comprend" qu'il faut aussi supprimer la ligne liée automatiquement.
Exemple
Disons qu'on a deux tables : customers et orders. Les clients (customers) peuvent passer plusieurs commandes (orders), donc c'est une relation ONE-TO-MANY. On veut que quand on supprime un client, toutes ses commandes disparaissent aussi.
-- On crée la table des clients
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- On crée la table des commandes avec une clé étrangère qui pointe vers la table des clients
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE,
order_date DATE NOT NULL
);
On insère des données dans les tables
-- On insère des données dans la table des clients
INSERT INTO customers (name) VALUES ('Ivan'), ('Anna');
-- On insère des données dans la table des commandes
INSERT INTO orders (customer_id, order_date) VALUES
(1, '2023-10-01'),
(1, '2023-10-02'),
(2, '2023-10-03');
Table orders :
| order_id | customer_id | order_date |
|---|---|---|
| 1 | 1 | 2023-10-01 |
| 2 | 1 | 2023-10-02 |
| 3 | 2 | 2023-10-03 |
On supprime un client et on regarde ce qui se passe
-- On supprime le client avec l'ID 1
DELETE FROM customers WHERE customer_id = 1;
-- On vérifie ce qu'il reste dans la table des commandes
SELECT * FROM orders;
| order_id | customer_id | order_date |
|---|---|---|
| 3 | 2 | 2023-10-03 |
Comme tu vois, les commandes liées au client supprimé ont été supprimées aussi.
Restriction des modifications : ON UPDATE RESTRICT
ON UPDATE RESTRICT permet d'empêcher la modification d'une valeur dans la table parente si une ligne dans la table enfant pointe dessus. C'est un peu comme un "pare-feu" qui bloque les modifs qui pourraient casser l'intégrité des données.
Comment ça marche ? Quand tu ajoutes ON UPDATE RESTRICT, la base ne te laissera pas mettre à jour la clé dans la table parente si elle est référencée dans la table enfant.
Exemple
On reprend les mêmes tables customers et orders, mais cette fois on ajoute la restriction sur la clé étrangère.
-- On recrée la table des commandes avec la restriction sur la mise à jour
DROP TABLE orders;
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id) ON UPDATE RESTRICT,
order_date DATE NOT NULL
);
Essayons de modifier l'ID du client
-- Tentative de changer l'ID du client de 2 à 5
UPDATE customers
SET customer_id = 5
WHERE customer_id = 2;
Résultat :
ERROR: update or delete on table "customers" violates foreign key constraint
DETAIL: Key (customer_id)=(2) is still referenced from table "orders".
Comme tu vois, la base a balancé une erreur parce que changer la clé aurait cassé le lien entre les tables.
Je t'expliquerai plus en détail UPDATE et ses subtilités au prochain niveau :P
Combiner ON DELETE CASCADE et ON UPDATE RESTRICT
Bien sûr, tu peux combiner les opérations en cascade (CASCADE) et les restrictions (RESTRICT). Par exemple, tu peux configurer la suppression automatique des données liées quand tu supprimes la ligne parente (ON DELETE CASCADE), mais interdire de changer son ID (ON UPDATE RESTRICT), pour éviter les galères.
Exemple
On va encore recréer la table des commandes, cette fois avec les deux mécanismes :
DROP TABLE orders;
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id)
ON DELETE CASCADE
ON UPDATE RESTRICT,
order_date DATE NOT NULL
);
Maintenant :
- Si tu supprimes un client, toutes ses commandes seront supprimées.
- Si tu essaies de changer l'ID du client, tu auras une erreur.
Pourquoi c'est important dans les vrais projets ?
L'utilisation de CASCADE et RESTRICT est super importante dans les gros systèmes avec plein de tables liées. Par exemple :
Dans un site e-commerce, un client peut avoir des commandes. Si le client veut supprimer son profil, tu veux pas garder dans la base des commandes qui ne pointent plus sur rien. Là, ON DELETE CASCADE te sauve la vie.
En même temps, tu veux sûrement empêcher les changements accidentels des clés uniques, pour pas casser les liens entre les tables. Pour ça, ON UPDATE RESTRICT est nickel.
GO TO FULL VERSION