informatique (MP2I/MPI) · Chapitre 21 · Application directe du cours
Problème — Trois cardinalités, une base
Bases de données relationnelles et SQL · niveau 3 (difficile)
Énoncé
On enrichit la base de trois tables :
| eleve | casier |
|---|---|
| 1 | 204 |
| 2 | 118 |
| 3 | 331 |
| id | nom |
|---|---|
| 100 | Achour |
| 101 | Bernard |
| 102 | Chan |
| prof | matiere | promo |
|---|---|---|
| 100 | 10 | 2026 |
| 100 | 10 | 2027 |
| 101 | 11 | 2026 |
| 101 | 11 | 2027 |
| 101 | 12 | 2026 |
| 102 | 10 | 2026 |
- Identifier les trois cardinalités présentes et dire où sont les clés étrangères.
- Écrire, pour chacune, une requête qui la parcourt.
- Écrire « quel professeur enseigne à quel élève ». Combien de jointures ?
- Que se passe-t-il si l'on oublie une condition de jointure ?
Corrigé
1. Les trois cardinalités.
| Association | type | où est la clé étrangère | remarque |
|---|---|---|---|
| Eleve — Dossier | Dossier.eleve | d'un seul côté | |
| Promotion — Eleve | Eleve.promo | côté « plusieurs » | |
| Professeur — Matiere | Enseigne | table intermédiaire |
Trois remarques que la figure rend visibles.
D'abord, Dossier et Enseigne se ressemblent : toutes deux portent une clé étrangère vers une autre table. Ce qui les sépare est que Dossier.eleve est la clé primaire de sa table — donc un élève a au plus un dossier — alors que Enseigne.prof n'est qu'une partie de la clé. La cardinalité se lit dans la clé primaire, pas dans la clé étrangère.
Ensuite, l'association n'est pas forcément totale : Dupont n'a pas de dossier. Mesuré, la jointure externe le montre :
SELECT e.nom, d.casier FROM Eleve e LEFT JOIN Dossier d ON d.eleve = e.id;
-- Alaoui 204 | Benali 118 | Cohen 331 | Dupont NULL
Enfin, Enseigne porte trois attributs en clé : le même professeur enseigne la même matière à deux promotions. La table intermédiaire n'est pas seulement un couple, elle est un triplet — et c'est la preuve que le programme a raison de dire qu'elle « porte souvent une information propre ».
2. Une requête par cardinalité.
-- 1-*
SELECT promo, COUNT(*) AS effectif FROM Eleve GROUP BY promo;
-- 2026 : 2 | 2027 : 2
-- *-*, parcouru dans les deux sens à la fois
SELECT p.nom AS professeur, m.intitule AS matiere, g.promo
FROM Enseigne g JOIN Professeur p ON p.id = g.prof
JOIN Matiere m ON m.code = g.matiere;
-- 6 lignes
-- *-*, agrégé d'un côté
SELECT m.intitule, COUNT(DISTINCT g.prof) AS nb_profs
FROM Matiere m LEFT JOIN Enseigne g ON g.matiere = m.code
GROUP BY m.code, m.intitule;
-- Informatique 2 | Mathématiques 1 | Physique 1
Le DISTINCT de la dernière n'est pas décoratif : Bernard enseigne les mathématiques à deux promotions, et sans lui on compterait deux professeurs de mathématiques.
3. Quel professeur enseigne à quel élève. Il n'existe aucune clé étrangère entre Eleve et Professeur : le lien passe par la matière et par la promotion. Quatre tables, donc trois jointures.
SELECT DISTINCT e.nom, p.nom AS professeur
FROM Eleve e
JOIN Note n ON n.eleve = e.id
JOIN Enseigne g ON g.matiere = n.matiere AND g.promo = e.promo
JOIN Professeur p ON p.id = g.prof
ORDER BY e.nom, p.nom;
Sept lignes mesurées : Alaoui avec Achour, Bernard et Chan ; Benali avec les mêmes trois ; Cohen avec Bernard seul.
Le ON à deux conditions est le cœur du problème. Une jointure sur la seule matière rapprocherait Cohen (promotion ) du professeur Chan, qui n'enseigne qu'en . La condition de recollement doit reproduire toute la clé de l'association — ici — et pas une partie. C'est l'exact analogue de la clé primaire composée de Note : une clé partielle donne une jointure partielle, et le résultat est faux sans être vide.
4. L'oubli. SELECT COUNT(*) FROM Eleve, Professeur rend : , le produit cartésien. Aucune erreur, aucun avertissement — seulement un résultat quatre fois trop grand, où chaque élève est associé à tous les professeurs. Sur une base réelle, c'est un résultat des millions de fois trop grand, et un serveur immobilisé.
En pratique — Compter les ON
Une règle qui ne coûte rien : tables dans le FROM demandent conditions de jointure. Quatre tables, trois ON. Si le compte n'y est pas, il y a un produit cartésien quelque part. C'est un contrôle syntaxique, vérifiable d'un coup d'œil, et il attrape le défaut le plus coûteux de SQL.