Les modèles relationnels
- Comprendre pourquoi on modélise avant de coder
- Lire un énoncé et identifier les entités, relations et cardinalités
- Construire un MCD clair et le traduire en MLD selon des règles précises
- Comprendre les trois types d'intégrité des données
- Appliquer les formes normales pour éliminer la redondance
Pourquoi modéliser ?
Avant d'écrire une seule ligne de SQL, il faut réfléchir à la structure des données : quelles informations doit-on stocker ? Comment sont-elles liées ? Quelles règles doivent être respectées ?
Construire une base de données sans modèle, c'est comme construire une maison sans plan d'architecte : on avance vite au début, puis tout s'effondre.
La méthode Merise propose une démarche en trois niveaux :
| Niveau | Objectif | Représentation | Acteur |
|---|---|---|---|
| MCD – Modèle Conceptuel | Décrire le "quoi" sans penser à la technique | Entités, relations, cardinalités | Analyste / Client |
| MLD – Modèle Logique | Traduire en tables relationnelles | Tables, clés primaires, clés étrangères | Concepteur |
| MPD – Modèle Physique | Implémenter dans un SGBD réel | SQL, index, contraintes physiques | Développeur |
MCD : Modèle Conceptuel des Données
Les quatre composants fondamentaux
Un MCD est composé de quatre briques :
Critère : si on peut en dresser une liste et stocker des informations dessus, c'est probablement une entité.
Exemples :
Client, Produit, Commande, Enseignant, CoursExemples pour
Client : idClient, nom, email, dateNaissanceExemples : Passe (entre Client et Commande), Enseigne (entre Enseignant et Cours), Habite (entre Personne et Ville)
(min, max) de chaque côté de l'association.[Client] --(0,N)-- <Passe> --(1,1)-- [Commande] idClient idCommande nom dateCommande email montantTotalLecture : Un client peut passer 0 à N commandes. Une commande est passée par exactement 1 client.
Les cardinalités en détail
Les cardinalités se lisent toujours du côté de l'entité vers l'association : "cette entité participe à cette association au minimum X fois et au maximum Y fois."
| Cardinalité | Signification | Exemple concret | Question à se poser |
|---|---|---|---|
| (0,1) | Facultatif, au plus une fois | Un employé peut avoir 0 ou 1 voiture de fonction | "Peut ne pas avoir de..." |
| (1,1) | Obligatoire, exactement une fois | Une commande appartient à exactement 1 client | "A toujours exactement un..." |
| (0,N) | Facultatif, zéro ou plusieurs | Un auteur peut avoir écrit 0 ou plusieurs livres | "Peut avoir plusieurs..." |
| (1,N) | Obligatoire, au moins une fois | Un cours a au moins 1 étudiant inscrit | "A toujours au moins un..." |
Méthode : "Un(e) [entité A] peut/doit participer à [relation] ... fois."
Pour
[Auteur] --(1,N)-- <Ecrit> --(1,1)-- [Livre] :→ Un auteur écrit au moins 1 livre (1,N)
→ Un livre est écrit par exactement 1 auteur (1,1)
Les trois types de relations
La combinaison des cardinalités de chaque côté détermine le type de relation :
| Type | Cardinalités | Exemple | Conséquence en MLD |
|---|---|---|---|
| 1 – 1 | (1,1) — (1,1) ou (0,1) — (1,1) | Une personne a un seul passeport | Clé étrangère dans l'une des deux tables |
| 1 – N | (1,1) — (0,N) ou (1,N) | Un département contient plusieurs employés | Clé étrangère dans la table "N" |
| N – M | (0,N) — (0,N) ou (1,N) — (1,N) | Des étudiants s'inscrivent à des cours | Table de liaison |
-- Relation 1-1 [Personne] --(1,1)-- <Possede> --(0,1)-- [Passeport]-- Relation 1-N [Departement] --(1,N)-- <Contient> --(1,1)-- [Employe]
-- Relation N-M [Etudiant] --(0,N)-- <Inscription> --(0,N)-- [Cours] note
Relations réflexives
Une relation peut lier une entité à elle-même. On parle de relation réflexive (ou récursive).
-- Un employé peut superviser d'autres employés [Employe] --(0,N)-- <Supervise> --(0,1)-- [Employe] idEmploye nom-- Des personnes peuvent être amies entre elles [Personne] --(0,N)-- <EstAmieDe> --(0,N)-- [Personne]
Traduction en MLD : une relation réflexive N-M génère une table de liaison avec deux clés étrangères pointant vers la même table, avec des noms de rôles différents.
Employe(idEmploye PK, nom, prenom)
Supervise(idSuperviseur FK -> Employe, idSubordonne FK -> Employe)
Les attributs d'association
Certains attributs n'appartiennent ni à une entité ni à l'autre, mais à la relation elle-même. Ils décrivent un fait qui n'existe que lorsque les deux entités sont liées.
[Etudiant] --(0,N)-- <Inscription> --(0,N)-- [Cours]
note ← attribut de la relation
dateInscription
La note n'appartient pas à l'étudiant seul (il a des notes différentes dans chaque cours), ni au cours seul. Elle existe uniquement dans le contexte de l'inscription.Si la réponse est non, c'est un attribut de l'association.
Construire un MCD à partir d'un énoncé
Construire un MCD depuis un texte suit une démarche méthodique en quatre étapes.
Étape 1 – Lire et annoter le texte
Chercher :
- Les noms → potentielles entités (personnes, objets, lieux, événements)
- Les verbes → potentielles associations
- Les quantificateurs ("un seul", "plusieurs", "au moins un") → cardinalités
Posez-vous toujours : "Qui ? Quoi ? Combien de fois ?"
Étape 2 – Identifier les entités
Une entité = quelque chose que le système doit mémoriser et à propos duquel on a plusieurs informations.
| Exemple | Entité ? | Raison |
|---|---|---|
Client | ✅ Oui | On stocke son nom, email, adresse... |
Commande | ✅ Oui | On stocke sa date, son montant, son statut... |
Rouge (couleur) | ❌ Non | C'est un attribut de Produit, pas une entité |
Achat (action ponctuelle) | ⚠️ Dépend | Si on a besoin de le tracer, oui ; sinon, c'est une relation |
Étape 3 – Identifier les associations et cardinalités
Une association lie deux entités. Elle est souvent portée par un verbe de l'énoncé.
Pour fixer la cardinalité, posez la question dans les deux sens :
"Un client peut passer combien de commandes ?" → (0,N) côté Client "Une commande appartient à combien de clients ?" → (1,1) côté Commande
| Phrase dans l'énoncé | Cardinalité suggérée |
|---|---|
| "Un seul / exactement un" | (1,1) |
| "Au moins un / toujours au moins un" | (1,N) |
| "Peut avoir plusieurs / zéro ou plusieurs" | (0,N) |
| "Au plus un / optionnel" | (0,1) |
Étape 4 – Définir les attributs
Chaque entité possède des attributs : les informations à stocker pour chaque occurrence.
Règles à respecter :
- Les attributs doivent être atomiques (une seule valeur par cellule).
- L'identifiant (
id...) doit être unique, numérique et sans signification métier — pas le numéro de sécurité sociale, ni l'email. - Un même attribut ne doit pas apparaître dans plusieurs entités sans raison.
| Attribut | Type recommandé | Exemple |
|---|---|---|
nom | VARCHAR(50) | "Durand" |
dateNaissance | DATE | "2007-05-21" |
idEtudiant | INT AUTO_INCREMENT | 1024 |
email | VARCHAR(100) | "alice@mail.fr" |
actif | BOOLEAN | true ou false |
prix | DECIMAL(10,2) | 19.99 |
- Stocker une liste dans un champ : "cours=Maths,Physique" → créer une relation N-M à la place.
- Dupliquer un attribut : mettre
nomClientdansCommande→ utiliser une clé étrangère. - Confondre entité et attribut :
Villepeut être un attribut (simple) ou une entité (si on stocke code postal, région, etc.). - Oublier l'identifiant : chaque entité doit avoir un identifiant unique.
Exemple guidé pas à pas
Chaque étudiant peut s'inscrire à plusieurs cours. Chaque inscription donne lieu à une note.
Chaque cours est dispensé par un seul enseignant, mais un enseignant peut enseigner plusieurs cours.
Étape 1 – Annotation :
"Une école gère ses enseignants (entité), ses étudiants (entité), et les cours (entité) proposés. Chaque étudiant peut s'inscrire (association) à plusieurs (0,N) cours. Chaque inscription donne lieu à une note (attribut de relation). Chaque cours est dispensé (association) par un seul (1,1) enseignant, mais un enseignant peut enseigner plusieurs (0,N) cours."
Étape 2 – Entités : Etudiant, Cours, Enseignant
Étape 3 – Associations et cardinalités :
| Association | Entité A | Card. A | Card. B | Entité B | Attribut |
|---|---|---|---|---|---|
| Inscription | Etudiant | (0,N) | (0,N) | Cours | note |
| Dispense | Enseignant | (1,N) | (1,1) | Cours | — |
Étape 4 – Attributs :
Etudiant: idEtudiant, nom, prenom, dateNaissanceCours: idCours, intitule, volumeHoraireEnseignant: idEnseignant, nom, prenom, specialite
MCD final :
[Enseignant] --(1,N)-- <Dispense> --(1,1)-- [Cours] --(0,N)-- <Inscription> --(0,N)-- [Etudiant]
idEnseignant idCours note idEtudiant
nom intitule nom
prenom volumeHoraire prenom
specialite dateNaissance
MLD : Modèle Logique des Données
Le MLD traduit le MCD en tables relationnelles, prêtes à être implémentées dans un SGBD.
Règles de passage MCD → MLD
Les règles sont systématiques selon le type de relation :
Règle 1 – Chaque entité devient une table
Entité [Etudiant] (idEtudiant, nom, prenom)
→ Table Etudiant(idEtudiant PK, nom, prenom)
Règle 2 – Relation 1–1 : clé étrangère dans l'une des deux tables
On place la clé étrangère du côté de l'entité dont la cardinalité est (0,1) ou (1,1) à la même extrémité que la plus petite cardinalité.
[Personne] --(1,1)-- <Possede> --(0,1)-- [Passeport]
→ Passeport(idPasseport PK, ..., idPersonne FK -> Personne)
Règle 3 – Relation 1–N : clé étrangère dans la table "N"
La clé étrangère va dans la table du côté (N).
[Departement] --(1,N)-- <Contient> --(1,1)-- [Employe]
→ Employe(idEmploye PK, ..., idDepartement FK -> Departement)
Règle 4 – Relation N–M : table de liaison
La relation devient une nouvelle table avec les deux clés étrangères en clé primaire composite. Les attributs de la relation rejoignent cette table.
[Etudiant] --(0,N)-- <Inscription(note)> --(0,N)-- [Cours]
→ Inscription(idEtudiant PK FK, idCours PK FK, note)
Règle 5 – Relation réflexive N–M : table de liaison avec rôles
[Employe] --(0,N)-- <Supervise> --(0,1)-- [Employe]
→ Supervise(idSuperviseur PK FK -> Employe, idSubordonne PK FK -> Employe)
Tableau récapitulatif
| Type de relation | Traduction MLD | Où va la clé étrangère ? |
|---|---|---|
| 1 – 1 | Clé étrangère dans une table | Côté (0,1) de préférence |
| 1 – N | Clé étrangère dans la table N | Dans la table côté (N) |
| N – M | Nouvelle table de liaison | Les deux clés en PK composite |
| N – M avec attribut | Table de liaison + colonnes | Attributs dans la table de liaison |
| Réflexive N–M | Table de liaison auto-référencée | Deux FK vers la même table |
Application sur l'exemple "École"
Enseignant(idEnseignant PK, nom, prenom, specialite)
Cours(idCours PK, intitule, volumeHoraire, idEnseignant FK -> Enseignant)
Etudiant(idEtudiant PK, nom, prenom, dateNaissance)
Inscription(idEtudiant PK FK -> Etudiant, idCours PK FK -> Cours, note)
Pourquoi idEnseignant va dans Cours (et non l'inverse) ?
La relation est 1–N : un enseignant enseigne plusieurs cours, un cours est enseigné par un seul enseignant. La clé étrangère va dans la table côté "1" de l'entité qui reçoit plusieurs : Cours porte idEnseignant.
Intégrité des données
Intégrité d'entité
Chaque enregistrement doit être identifiable de manière unique.
- La clé primaire ne peut jamais être
NULL. - Deux lignes ne peuvent avoir la même valeur de clé primaire.
CREATE TABLE Etudiant (
idEtudiant INT PRIMARY KEY AUTO_INCREMENT, -- unique, jamais NULL
nom VARCHAR(50) NOT NULL,
prenom VARCHAR(50) NOT NULL
);
Intégrité référentielle
Une clé étrangère doit toujours pointer vers une valeur qui existe dans la table référencée.
CREATE TABLE Inscription (
idEtudiant INT,
idCours INT,
FOREIGN KEY (idEtudiant) REFERENCES Etudiant(idEtudiant) ON DELETE CASCADE,
FOREIGN KEY (idCours) REFERENCES Cours(idCours) ON DELETE RESTRICT
);
| Comportement | ON DELETE CASCADE | ON DELETE RESTRICT |
|---|---|---|
| Si l'étudiant est supprimé | Ses inscriptions sont supprimées aussi | Erreur — impossible de supprimer |
| Utilisation typique | Données dépendantes (inscriptions) | Données indépendantes (cours) |
Intégrité de domaine
Chaque colonne doit respecter un type et des contraintes de valeur.
CREATE TABLE Produit (
idProduit INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(100) NOT NULL,
prix DECIMAL(10,2) CHECK (prix >= 0),
stock INT DEFAULT 0,
actif BOOLEAN DEFAULT TRUE
);
| Contrainte | Rôle |
|---|---|
NOT NULL | Valeur obligatoire |
CHECK (...) | Condition à respecter |
DEFAULT | Valeur par défaut si non renseignée |
UNIQUE | Pas deux fois la même valeur dans cette colonne |
Normalisation et Formes Normales
Pourquoi normaliser ?
Imaginez une table qui stocke toutes les informations d'une commande dans une seule ligne :
| idCommande | client | ville | produit | prix | qte |
|---|---|---|---|---|---|
| 1 | Alice | Paris | Clavier | 40 | 2 |
| 2 | Alice | Paris | Souris | 15 | 1 |
| 3 | Bob | Lyon | Clavier | 40 | 1 |
Problèmes :
- Si Alice déménage, il faut modifier toutes ses commandes → anomalie de mise à jour
- Si on supprime la commande 3, on perd le prix du Clavier → anomalie de suppression
- On ne peut pas ajouter un produit sans créer une commande → anomalie d'insertion
La normalisation élimine ces problèmes en décomposant les tables selon des règles précises.
Dépendances fonctionnelles
Exemples :
idEtudiant → nom : un id d'étudiant détermine un seul nomidProduit → prixUnitaire : un id de produit détermine un seul prixville → codePostal : une ville détermine un seul code postal (approximativement)Les dépendances fonctionnelles sont le fondement des formes normales.
Première Forme Normale (1NF)
Avant (non 1NF) :
| idCommande | produits |
|---|---|
| 1 | Clavier, Souris, Écran |
| 2 | Clavier |
Après (1NF) :
| idCommande | produit |
|---|---|
| 1 | Clavier |
| 1 | Souris |
| 1 | Écran |
| 2 | Clavier |
Autre violation 1NF – colonnes répétées :
| idClient | produit1 | produit2 | produit3 |
|---|---|---|---|
| 1 | Clavier | Souris | — |
→ Même problème : on ne peut pas ajouter un 4e produit sans modifier la structure.
Deuxième Forme Normale (2NF)
La 2NF ne concerne que les tables avec une clé primaire composite.
Avant (non 2NF) — clé = (idCommande, idProduit) :
| idCommande | idProduit | nomProduit | prixUnitaire | quantite |
|---|---|---|---|---|
| 10 | P01 | Clavier | 40 | 2 |
| 10 | P02 | Souris | 15 | 1 |
| 11 | P01 | Clavier | 40 | 3 |
Problème : nomProduit et prixUnitaire dépendent seulement de idProduit, pas de (idCommande, idProduit). Si le prix du clavier change, il faut mettre à jour plusieurs lignes.
Après (2NF) — on sépare les attributs selon leur dépendance :
| idProduit (PK) | nomProduit | prixUnitaire |
|---|---|---|
| P01 | Clavier | 40 |
| P02 | Souris | 15 |
| idCommande (PK) | idProduit (PK, FK) | quantite |
|---|---|---|
| 10 | P01 | 2 |
| 10 | P02 | 1 |
| 11 | P01 | 3 |
Troisième Forme Normale (3NF)
Avant (non 3NF) :
| idClient (PK) | nomClient | ville | codePostal |
|---|---|---|---|
| 1 | Alice | Paris | 75001 |
| 2 | Bob | Lyon | 69001 |
Problème : codePostal dépend de ville, pas de idClient directement. Chaîne : idClient → ville → codePostal → dépendance transitive
Après (3NF) :
| idClient (PK) | nomClient | ville |
|---|---|---|
| 1 | Alice | Paris |
| 2 | Bob | Lyon |
| ville (PK) | codePostal |
|---|---|
| Paris | 75001 |
| Lyon | 69001 |
Résumé des formes normales
| Forme | Règle | Anomalie éliminée |
|---|---|---|
| 1NF | Valeurs atomiques, pas de colonnes répétées | Données multivaluées non structurées |
| 2NF | Pas de dépendance partielle à la clé | Redondance liée aux clés composites |
| 3NF | Pas de dépendance transitive | Redondance en chaîne entre attributs |
- 1NF : "Est-ce qu'une cellule peut contenir plusieurs valeurs ?" → Si oui, séparer.
- 2NF : "Cet attribut dépend-il de toute la clé, ou d'une partie seulement ?" → Si partiel, déplacer.
- 3NF : "Cet attribut dépend-il d'un autre attribut non-clé ?" → Si oui, extraire dans une table séparée.
Exemple complet : système scolaire avec tutorat
Chaque élève est inscrit dans une seule classe.
Chaque classe est encadrée par un enseignant responsable. Un enseignant peut être responsable de plusieurs classes, ou d'aucune.
L'école organise un système de tutorat : certains enseignants accompagnent individuellement certains élèves dans un rôle défini (ex : "référent", "soutien").
Un élève peut avoir été inscrit plusieurs années de suite dans la même classe (redoublement).
Entités et attributs
| Entité | Attributs | Remarque |
|---|---|---|
Eleve | idEleve, nom, prenom, dateNaissance | |
Classe | idClasse, nomClasse | Ex : "5A", "6B" |
Enseignant | idEnseignant, nom, prenom, dateEmbauche |
Relations et cardinalités
| Relation | De | Card. | Card. | Vers | Attributs |
|---|---|---|---|---|---|
| EstInscrit | Eleve | (1,N) | (1,1) | Classe | annee (redoublement) |
| ResponsableDe | Enseignant | (0,N) | (1,1) | Classe | — |
| Tutorat | Enseignant | (0,N) | (0,N) | Eleve | role |
MCD
[Enseignant] --(0,N)-- <ResponsableDe> --(1,1)-- [Classe] --(1,N)-- <EstInscrit(annee)> --(1,1)-- [Eleve]
↑
[Enseignant] --(0,N)-- <Tutorat(role)> --(0,N)-- [Eleve]
MLD
Enseignant(idEnseignant PK, nom, prenom, dateEmbauche)
Classe(idClasse PK, nomClasse, idEnseignant FK -> Enseignant)
Eleve(idEleve PK, nom, prenom, dateNaissance)
EstInscrit(idEleve PK FK -> Eleve, idClasse PK FK -> Classe, annee PK)
Tutorat(idEnseignant PK FK -> Enseignant, idEleve PK FK -> Eleve, role)
Pourquoi annee est-il dans la clé primaire de EstInscrit ? Sans annee, un élève ne peut être inscrit qu'une seule fois dans une classe. Pour permettre le redoublement (même élève, même classe, année différente), on l'inclut dans la clé composite.
- Lire le texte : annoter noms (entités), verbes (relations), quantificateurs (cardinalités).
- Construire le MCD : entités, attributs, associations, cardinalités.
- Traduire en MLD : appliquer les règles selon le type de relation (1-1, 1-N, N-M).
- Vérifier la normalisation : 1NF → 2NF → 3NF.
- Implémenter en SQL : CREATE TABLE avec clés et contraintes.
