La normalisation n'est pas une suggestion bureaucratique.
C'est la loi de la gravité qui empêche votre architecture de s'effondrer.
Tous les défis tournent sur un vrai jeu de données PostgreSQL : 50 clients, 200 000 achats, des fantômes et de la pollution.
createdb -h localhost -U postgres sqlfun psql -h localhost -U postgres -d sqlfun -f jeu-de-donnees-sql-fun.sql
Ou dans pgAdmin 4 : créer la base sqlfun, ouvrir le fichier dans l'outil de requête, puis Exécuter (F5).
Un collègue a importé ce fichier Excel dans votre base de données relationnelle :
| Commande_ID | Client | Produits_Achetés |
|---|---|---|
| 101 | Alice | Clavier, Souris, Écran |
Le cauchemar : Trouvez tous les clients qui ont acheté une "Souris".
Mission de déconstruction
Au tableau : Atomisez ces données pour que chaque cellule ne contienne qu'une seule valeur. Combien de tables obtenez-vous ?
Une cellule, une valeur. Chaque produit acheté devient sa propre ligne :
| commande | commande_produit |
|---|---|
| 101, Alice | 101, Clavier 101, Souris 101, Écran |
Réponse : 2 tables, 3 avec un catalogue produit. La Souris se trouve avec un simple WHERE produit = 'Souris'.
⚖️ La loi que vous venez d'appliquer : la première forme normale (1NF), une cellule, une valeur, jamais de liste.
💀 Mode hardcore : atomisez la table commande_brute de l'arène sans rien retaper, avec string_to_array() et unnest().
La table `LIGNE_COMMANDE` a une clé composée : (Commande_ID, Produit_ID).
| Commande_ID | Produit_ID | Quantité | Nom_Produit | Prix |
|---|---|---|---|---|
| 101 | A1 | 1 | RAM 16GB | 89.99 |
| 102 | A1 | 4 | RAM 16GB | 89.99 |
Quelles colonnes ne dépendent que d'une moitié de la clé ? Découpez la table pour que chaque colonne dépende de toute la clé.
Nom_Produit et Prix ne dépendent que de Produit_ID : c'est une dépendance partielle. ⚖️ La loi qui l'interdit : la deuxième forme normale (2NF).
| produit | ligne_commande |
|---|---|
| produit_id (clé), nom, prix | commande_id, produit_id (clé étrangère), quantité |
La 2NF ne concerne que les clés composées : une table en 1NF à clé simple est automatiquement en 2NF.
💀 Mode hardcore : dans l'arène, comptez combien de fois chaque nom de produit est répété dans ligne_commande_brute.
Une table `PRODUITS` contient 10 millions de lignes. Le numéro de téléphone de votre fournisseur "TechCorp" vient de changer.
| Produit_ID | Nom | Fournisseur | Tel_Fournisseur |
|---|---|---|---|
| A1 | RAM 16GB | TechCorp | 555-0101 |
| A2 | SSD 1TB | TechCorp | 555-0101 |
Diagnostic d'urgence
1. Que se passe-t-il techniquement lors de cette modification sur 10 millions de lignes ?
2. Quelle est la structure mathématique (clés étrangères) pour corriger cette dépendance toxique ?
1. L'UPDATE réécrit 10 millions de lignes pour une seule information. Si une ligne échappe au WHERE, TechCorp a deux téléphones : la base se contredit.
2. Le téléphone dépend du fournisseur, pas du produit (dépendance transitive). On le sort :
CREATE TABLE fournisseur ( id SERIAL PRIMARY KEY, nom VARCHAR(40), telephone VARCHAR(20)); CREATE TABLE produit ( id VARCHAR(10) PRIMARY KEY, nom VARCHAR(40), fournisseur_id INTEGER REFERENCES fournisseur (id));
Le numéro change en une seule ligne. ⚖️ La loi : la troisième forme normale (3NF), rien ne dépend d'autre chose que la clé.
La même table `PRODUITS` cache deux autres anomalies.
1. Insertion : un nouveau fournisseur, NanoChip, n'a encore aucun produit. Où inscrire son téléphone ?
2. Suppression : on retire du catalogue le seul produit de VisionPlus. Que perd-on au passage ?
1. Anomalie d'insertion : impossible sans inventer un faux produit, puisque Produit_ID est obligatoire.
2. Anomalie de suppression : le téléphone de VisionPlus disparaît avec son dernier produit.
La table fournisseur de la solution 2 règle les trois anomalies d'un coup : un fait, une seule place.
Pourquoi vous imposer cette rigidité mathématique absolue ?
Parce qu'il est impossible de maîtriser la liberté sauvage et déstructurée du NoSQL ou des documents JSON si l'on ne comprend pas d'abord ce que l'on déconstruit.
Il faut comprendre les règles de l'Univers avant de jouer avec le chaos.
Les experts violent la normalisation, mais seulement quand ils savent exactement ce qu'ils cassent. Ça s'appelle la dénormalisation.
⚡ Lecture rapide : recopier le nom du client dans la facture pour éviter une jointure sur un écran consulté des millions de fois.
📦 Cache : une vue matérialisée garde des totaux déjà calculés.
🍃 NoSQL : un document MongoDB contient ses commandes imbriquées, exprès.
Le prix : garder les copies synchronisées. Qui brise la loi en paie la dette.