Adloun

Une table qui se répète, deux tables qui ne se répètent pas

Exercice d'entraînement · niveau 3 (difficile) · mathématiques appliquées (ECG 2e année), chapitre 13 — Bases de données et travaux pratiques · Modèle relationnel et schéma

Énoncé

Une entreprise conserve toutes ses ventes dans une unique table vente(id, client_nom, client_ville, montant), où le nom et la ville du client sont recopiés à chaque vente. Indiquer deux défauts de cette organisation, puis écrire le schéma de deux tables qui les corrigent.

Corrigé

Premier défaut : la redondance. Un client qui a passé cinquante commandes voit son nom et sa ville recopiés cinquante fois. L'espace occupé est inutile, mais ce n'est pas le pire.

Second défaut : l'incohérence possible. Si ce client déménage, il faut modifier cinquante lignes. Un UPDATE mal filtré n'en modifiera que quarante-neuf, et la base contiendra alors deux villes différentes pour le même client, sans qu'aucune règle ne signale la contradiction. La table ne sait même pas que ces cinquante lignes désignent la même personne.

On en ajouterait un troisième : un client qui n'a encore rien acheté ne peut pas être enregistré du tout, puisqu'il n'a aucune ligne de vente.

La correction. On sépare ce qui décrit le client de ce qui décrit la vente, et l'on relie les deux par une clef.


CREATE TABLE client (
    id     INTEGER PRIMARY KEY,
    nom    TEXT,
    ville  TEXT
);

CREATE TABLE vente (
    id         INTEGER PRIMARY KEY,
    client_id  INTEGER,
    montant    INTEGER,
    FOREIGN KEY (client_id) REFERENCES client(id)
);

Ce que la séparation garantit. Chaque client est décrit une seule fois : un déménagement se corrige par un unique UPDATE sur client, et l'incohérence devient impossible. Un client sans vente existe désormais. Et la clef étrangère interdit d'enregistrer une vente attribuée à un client inconnu.

Ce qu'elle coûte. L'information n'est plus lisible d'un seul coup d'œil : pour afficher le nom du client à côté du montant, il faut désormais une jointure,


SELECT client.nom, vente.montant
FROM vente
INNER JOIN client ON vente.client_id = client.id;

C'est le compromis fondamental du modèle relationnel : on paie en jointures ce qu'on gagne en cohérence.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.