Deux adresses pour une cliente
Claire Martin a changé d'adresse e-mail. Un collègue l'a corrigée sur sa dernière vente seulement.
Aujourd'hui, la base de Cycles Loire donne deux adresses pour la même cliente. La facture part à l'ancienne, la confirmation à la nouvelle. Le problème ne vient pas du collègue. Il vient de la façon dont la table a été pensée.
À la fin de cette leçon
Remarque
Je peux répartir des données en tables pour que chaque information soit écrite une seule fois.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Doublon | la même information écrite plusieurs fois | |
| Incohérence | deux copies d'une information qui ne disent plus la même chose | |
| Normalisation | découper les tables pour écrire chaque information une fois | |
| Entité | une chose dont on garde les informations | client, produit |
| NoSQL | des bases qui rangent les données autrement qu'en tables reliées |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une table fourre-tout répète les faits
Au début, la boutique notait tout dans une seule table ventes : le client, son e-mail, le produit, le prix.
Claire a acheté trois fois. Son nom et son e-mail sont donc écrits trois fois. Chaque copie est un doublon. Il suffit d'en corriger une sur trois pour créer une incohérence. Lancez le bloc suivant pour la voir.
Essayez : repérer l'incohérence
-- Combien d'adresses différentes pour Claire Martin ?
SELECT client, email, COUNT(*) AS lignes
FROM ventes
GROUP BY client, email;
-- Une seule cliente, deux adresses : laquelle est la bonne ?
Une table par entité
La solution est de découper. On cherche les entités : ici, les clients, les produits et les ventes.
Chaque entité a sa table et sa clé primaire. L'e-mail de Claire est écrit une fois, dans clients. Le prix du casque est écrit une fois, dans produits. Une vente ne garde que deux clés étrangères. C'est la normalisation.
Essayez : une seule ligne à changer
-- Claire change d'adresse : une seule ligne à modifier.
UPDATE clients SET email = '[email protected]' WHERE id = 1;
-- Les ventes retrouvent le nom, l'adresse et le prix par jointure.
SELECT ventes.id, clients.nom, clients.email, produits.nom, produits.prix
FROM ventes
JOIN clients ON ventes.client_id = clients.id
JOIN produits ON ventes.produit_id = produits.id;
Exemple détaillé : avant et après
| Question | Une table fourre-tout | Trois tables |
|---|---|---|
| Lignes à changer quand Claire change d'e-mail | 3 | 1 |
| Fois où le prix du casque est écrit | 2 | 1 |
| Jointures pour afficher une vente complète | 0 | 2 |
| Risque de deux adresses pour une cliente | Oui | Non |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur fréquente
Attention
Beaucoup pensent qu'il faut découper le plus possible. C'est faux. Découpez quand une information se répète et peut changer, comme un e-mail. Chaque table de plus ajoute une jointure à chaque lecture. Le bon découpage est celui qui écrit chaque fait une fois, sans plus.
Quand une base NoSQL convient
Les bases NoSQL rangent souvent des documents plutôt que des tables reliées. Un document regroupe tout ce qu'on lit ensemble, comme une fiche produit.
C'est pratique quand chaque fiche a des champs différents, ou quand on lit tout d'un bloc. Pour des clients, des commandes et de l'argent, reliés et souvent modifiés, une base en tables reste le choix courant.
Essayez : une fiche produit en document
# Un document : tout ce qu'on lit ensemble, rangé d'un bloc.
fiche = {
"nom": "Vélo cargo Loire",
"prix": 2490,
"caracteristiques": {"charge_max_kg": 80, "assistance": "electrique"},
"couleurs": ["vert", "gris"],
}
print(fiche["nom"], "coûte", fiche["prix"], "euros")
print("Couleurs :", fiche["couleurs"])
# Un antivol n'a pas de charge maximale : sa fiche aurait d'autres champs.