Modélisation BDD MERISE & UML
Concevoir une base de données de A à Z : MCD, MLD, MPD, cardinalités, normalisation et diagrammes UML.
Modéliser une base de données se fait en trois étapes progressives : du plus abstrait (conceptuel) au plus concret (physique). La méthode MERISE est la référence francophone.
| Niveau | Modèle | Objectif | Résultat |
|---|---|---|---|
| Conceptuel | MCD |
Représenter le besoin métier, indépendant de la technologie | Entités, associations, cardinalités |
| Logique | MLD |
Traduire le MCD en tables relationnelles | Tables, clés primaires, clés étrangères |
| Physique | MPD |
Implémenter en SQL sur un SGBD précis | Instructions CREATE TABLE avec types réels |
Chaque niveau se transforme en appliquant des règles précises.
Analyse du besoin
│
▼
┌─────────────────────────────────────────┐
│ MCD — Modèle Conceptuel de Données │ ← Entités, associations, cardinalités
│ "Quoi ?" — vision métier │
└────────────────────┬────────────────────┘
│ Application des règles de passage
▼
┌─────────────────────────────────────────┐
│ MLD — Modèle Logique de Données │ ← Tables, PK, FK (notation relationnelle)
│ "Comment ?" — vision relationnelle │
└────────────────────┬────────────────────┘
│ Choix du SGBD + types de données
▼
┌─────────────────────────────────────────┐
│ MPD — Modèle Physique de Données │ ← CREATE TABLE, INDEX, contraintes SQL
│ "Avec quoi ?" — vision technique │
└─────────────────────────────────────────┘
Une entité représente un objet réel ou abstrait du domaine métier, identifiable de façon unique. Elle regroupe des objets partageant les mêmes caractéristiques.
┌──────────────────────┐
│ CLIENT │ ← Nom de l'entité (toujours au singulier, en majuscules)
├──────────────────────┤
│ #id_client │ ← Identifiant (clé primaire) — noté avec #
│ nom │ ← Attribut simple
│ prenom │
│ email │
│ telephone │
└──────────────────────┘
Une occurrence est une instance de l'entité (ex : le client Jean Dupont).
| Type | Description | Exemple |
|---|---|---|
#identifiant |
Attribut unique qui identifie chaque occurrence. Devient la clé primaire. | #id_client |
simple |
Valeur atomique, indivisible | nom, email |
composé |
Peut être décomposé en sous-attributs (à éviter en BDD relationnelle) | adresse → rue, ville, CP |
calculé |
Dérivé d'autres attributs, non stocké directement | age (calculé depuis date_naissance) |
multivalué |
Peut avoir plusieurs valeurs — à transformer en entité séparée | telephones (multiple) |
Une association représente un lien entre deux ou plusieurs entités. Elle peut porter des attributs propres (données propres à la relation).
┌──────────┐ ┌───────────┐
│ CLIENT │ │ COMMANDE │
└────┬─────┘ └─────┬─────┘
│ 1,n 1,1 │
└──────────────── PASSER ───────────────────┘
(association)
┌──────────┐ ┌───────────┐
│ COMMANDE │ │ PRODUIT │
└────┬─────┘ └─────┬─────┘
│ 1,n quantite, prix_unitaire 0,n │
└────────────── CONTENIR ─────────────────┘
(avec attributs)
La cardinalité se lit du côté de l'entité concernée : "Une occurrence de cette entité participe à combien d'associations ?"
Format : (min, max) — min toujours 0 ou 1, max toujours 1 ou n.
| Cardinalité | Lecture | Exemple concret |
|---|---|---|
(0,1) |
Zéro ou une fois | Un employé peut avoir 0 ou 1 bureau attribué |
(1,1) |
Exactement une fois (obligatoire) | Une commande est passée par exactement 1 client |
(0,n) |
Zéro ou plusieurs fois | Un client peut avoir 0 ou plusieurs commandes |
(1,n) |
Une ou plusieurs fois (obligatoire) | Une commande contient au moins 1 produit |
| Type | Cardinalités côté A / côté B | Traduction MLD | Exemple |
|---|---|---|---|
| 1:1 | (1,1) — (0,1) ou (1,1) |
FK dans l'une des deux tables | Personne ↔ Passeport |
| 1:N | (1,n) ou (0,n) — (1,1) ou (0,1) |
FK du côté « 1 » dans la table « N » | Client ↔ Commandes |
| N:N | (0,n) ou (1,n) — (0,n) ou (1,n) |
Table de jonction avec deux FK | Commande ↔ Produits |
Le MCD décrit le domaine métier de façon indépendante de toute technologie. Il répond à la question "Qu'est-ce qu'on gère ?" sans se préoccuper du SGBD.
Il est composé :
— Entités : rectangles avec identifiant et attributs
— Associations : nommées par un verbe à l'infinitif
— Cardinalités : notées sur chaque patte de l'association
Schéma complet avec entités, associations et cardinalités pour un système de commandes en ligne.
┌──────────────────────┐ ┌──────────────────────┐
│ CLIENT │ │ CATEGORIE │
├──────────────────────┤ ├──────────────────────┤
│ #id_client │ │ #id_categorie │
│ nom │ │ libelle │
│ prenom │ │ description │
│ email │ └──────────┬───────────┘
│ telephone │ │ 1,n
│ adresse │ APPARTENIR
└──────────┬───────────┘ │ 1,1
│ 1,n ┌──────────┴───────────┐
PASSER │ PRODUIT │
│ 1,1 ├──────────────────────┤
┌──────────┴───────────┐ │ #id_produit │
│ COMMANDE │ │ designation │
├──────────────────────┤ │ prix_unitaire │
│ #id_commande │ │ stock │
│ date_commande │ └──────────┬───────────┘
│ statut │ │ 0,n
│ adresse_livraison │ CONTENIR
└──────────┬───────────┘ (quantite, remise)
│ 1,n │ 1,n
└──────────────────────────────┘
Lecture : Un client passe 1 ou plusieurs commandes (1,n). Une commande est passée par exactement 1 client (1,1). Une commande contient 1 ou plusieurs produits (1,n). Un produit peut être dans 0 ou plusieurs commandes (0,n) — l'association CONTENIR porte les attributs quantite et remise.
| Règle | Description |
|---|---|
| Identifiant unique | Chaque entité doit avoir un identifiant qui distingue chaque occurrence |
| Pas de doublon | Un attribut ne doit apparaître que dans une seule entité ou association |
| Cardinalités obligatoires | Chaque patte d'association doit porter une cardinalité (min, max) |
| Verbe d'action | Le nom de l'association doit être un verbe à l'infinitif actif ou passif |
| Attributs de relation | Les attributs propres à une relation N:N se placent sur l'association |
| Pas de redondance | Deux associations ne doivent pas exprimer le même lien sémantique |
Le MLD traduit le MCD en un modèle relationnel — des tables avec des colonnes. Il est indépendant du SGBD mais suit le modèle relationnel. La notation standard est :
NOM_TABLE (clé_primaire, attribut1, attribut2, #clé_etrangere)
Conventions :
• Clé primaire : soulignée ou en MAJUSCULES
• Clé étrangère : précédée de # ou suffixe _id, en italique
• Clé primaire composée : les deux colonnes soulignées
Traduction du MCD précédent en modèle logique. Les clés primaires sont soulignées, les clés étrangères sont préfixées de #.
CLIENT (id_client, nom, prenom, email, telephone, adresse)
‾‾‾‾‾‾‾‾‾‾‾‾
CATEGORIE (id_categorie, libelle, description)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾
PRODUIT (id_produit, designation, prix_unitaire, stock, #id_categorie)
‾‾‾‾‾‾‾‾‾‾‾‾
└─ #id_categorie référence CATEGORIE(id_categorie)
COMMANDE (id_commande, date_commande, statut, adresse_livraison, #id_client)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾
└─ #id_client référence CLIENT(id_client)
LIGNE_COMMANDE (id_commande, id_produit, quantite, remise)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
PK composée : (id_commande, id_produit)
└─ #id_commande référence COMMANDE(id_commande)
└─ #id_produit référence PRODUIT(id_produit)
Le MPD est la traduction du MLD en instructions SQL concrètes, adaptées à un SGBD précis (MySQL, PostgreSQL, SQLite…). On y précise les types de données, les contraintes, les index.
Implémentation SQL complète du MLD précédent sous MySQL.
-- Table CLIENT
CREATE TABLE client (
id_client INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(100) NOT NULL,
prenom VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
telephone VARCHAR(20),
adresse TEXT
);
-- Table CATEGORIE
CREATE TABLE categorie (
id_categorie INT PRIMARY KEY AUTO_INCREMENT,
libelle VARCHAR(100) NOT NULL UNIQUE,
description TEXT
);
-- Table PRODUIT (FK vers categorie)
CREATE TABLE produit (
id_produit INT PRIMARY KEY AUTO_INCREMENT,
designation VARCHAR(255) NOT NULL,
prix_unitaire DECIMAL(10,2) NOT NULL CHECK (prix_unitaire >= 0),
stock INT NOT NULL DEFAULT 0 CHECK (stock >= 0),
id_categorie INT NOT NULL,
FOREIGN KEY (id_categorie) REFERENCES categorie(id_categorie)
ON DELETE RESTRICT ON UPDATE CASCADE
);
-- Table COMMANDE (FK vers client)
CREATE TABLE commande (
id_commande INT PRIMARY KEY AUTO_INCREMENT,
date_commande DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
statut ENUM('en_attente','validee','expediee','livree','annulee')
NOT NULL DEFAULT 'en_attente',
adresse_livraison TEXT NOT NULL,
id_client INT NOT NULL,
FOREIGN KEY (id_client) REFERENCES client(id_client)
ON DELETE RESTRICT ON UPDATE CASCADE
);
-- Table LIGNE_COMMANDE (table de jonction N:N avec attributs)
CREATE TABLE ligne_commande (
id_commande INT NOT NULL,
id_produit INT NOT NULL,
quantite INT NOT NULL CHECK (quantite > 0),
remise DECIMAL(5,2) NOT NULL DEFAULT 0.00,
PRIMARY KEY (id_commande, id_produit),
FOREIGN KEY (id_commande) REFERENCES commande(id_commande)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (id_produit) REFERENCES produit(id_produit)
ON DELETE RESTRICT ON UPDATE CASCADE
);
-- Index pour les colonnes fréquemment filtrées
CREATE INDEX idx_produit_categorie ON produit(id_categorie);
CREATE INDEX idx_commande_client ON commande(id_client);
CREATE INDEX idx_commande_statut ON commande(statut);
Ces règles s'appliquent mécaniquement pour passer du MCD au MLD.
| Situation dans le MCD | Résultat dans le MLD |
|---|---|
| Entité | → Une table avec l'identifiant comme clé primaire |
Relation 1:N(1,1) ── assoc ── (0,n) |
→ La clé primaire du côté « 1 » migre comme clé étrangère dans la table côté « N » |
Relation 1:1(1,1) ── assoc ── (0,1) |
→ FK dans la table la plus faible (côté 0,1) ; ou fusion des deux tables si relation totale |
Relation N:N(1,n) ── assoc ── (0,n) |
→ Une nouvelle table de jonction avec les deux clés primaires (PK composée) + les attributs de l'association |
| Association ternaire (3 entités reliées) |
→ Table de jonction avec les 3 clés primaires des entités + attributs de l'association |
| Attribut de l'association (sur relation N:N) |
→ Colonne dans la table de jonction |
| Élément MLD | Traduction SQL (MySQL / PostgreSQL) |
|---|---|
| Table | CREATE TABLE nom_table (...) |
| Clé primaire simple | id INT PRIMARY KEY AUTO_INCREMENT (MySQL) / SERIAL PRIMARY KEY (PostgreSQL) |
| Clé primaire composée | PRIMARY KEY (col1, col2) en fin de table |
| Clé étrangère | FOREIGN KEY (col) REFERENCES autre_table(pk) ON DELETE ... ON UPDATE ... |
| Contrainte NOT NULL | Attribut obligatoire : NOT NULL |
| Contrainte UNIQUE | Attribut unique : UNIQUE |
| Valeur par défaut | DEFAULT valeur |
| Contrainte métier | CHECK (condition) |
| Option | Comportement | Usage typique |
|---|---|---|
RESTRICT |
Interdit la suppression/modification si des lignes liées existent | Protection des données critiques |
CASCADE |
Propage la suppression/modification aux lignes liées | Tables de jonction, données dépendantes |
SET NULL |
Met la FK à NULL dans les lignes liées | Relation optionnelle (la FK doit être nullable) |
SET DEFAULT |
Remet la FK à sa valeur DEFAULT dans les lignes liées | Rare, peu supporté |
NO ACTION |
Identique à RESTRICT (vérification différée possible) | Standard SQL, comportement par défaut |
La normalisation élimine les redondances et les anomalies de mise à jour dans une base de données. Elle s'applique progressivement via les formes normales.
| Anomalie | Problème |
|---|---|
Insertion | Impossible d'insérer une donnée sans en insérer une autre (ex: ajouter un produit sans commande) |
Mise à jour | La même info est stockée à plusieurs endroits : une seule modif ne suffit pas |
Suppression | Supprimer une ligne entraîne la perte d'autres informations |
Règle : Tous les attributs doivent être atomiques (indivisibles) et il ne doit pas y avoir de groupes répétitifs.
COMMANDE (id_commande, client, produits)
┌─────────────┬──────────────┬─────────────────────────────────┐
│ id_commande │ client │ produits │
├─────────────┼──────────────┼─────────────────────────────────┤
│ 1 │ Jean Dupont │ "Stylo x2, Cahier x1, Règle x3" │ ← non atomique !
│ 2 │ Marie Martin │ "Livre x1" │
└─────────────┴──────────────┴─────────────────────────────────┘
COMMANDE (id_commande, id_client)
LIGNE_COMMANDE (id_commande, id_produit, quantite)
┌─────────────┬────────────┐ ┌─────────────┬────────────┬──────────┐
│ id_commande │ id_client │ │ id_commande │ id_produit │ quantite │
├─────────────┼────────────┤ ├─────────────┼────────────┼──────────┤
│ 1 │ 1 │ │ 1 │ 101 │ 2 │
│ 2 │ 2 │ │ 1 │ 102 │ 1 │
└─────────────┴────────────┘ │ 1 │ 103 │ 3 │
│ 2 │ 104 │ 1 │
└─────────────┴────────────┴──────────┘
Règle : Être en 1NF ET tous les attributs non-clés doivent dépendre de la totalité de la clé primaire (pas d'une partie seulement). S'applique principalement aux PK composées.
LIGNE_COMMANDE (id_commande, id_produit, quantite, nom_produit, prix_produit)
PK = (id_commande, id_produit)
Problème :
• quantite → dépend de (id_commande + id_produit) ✓
• nom_produit → dépend uniquement de id_produit ✗ dépendance partielle !
LIGNE_COMMANDE (id_commande, id_produit, quantite)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
PRODUIT (id_produit, nom_produit, prix_produit, ...)
‾‾‾‾‾‾‾‾‾‾
nom_produit et prix_produit ont été déplacés dans leur propre entité PRODUIT.
Règle : Être en 2NF ET aucun attribut non-clé ne doit dépendre d'un autre attribut non-clé (pas de dépendance transitive).
EMPLOYE (id_employe, nom, id_departement, nom_departement, localisation)
PK = id_employe
Problème :
• id_departement → dépend de id_employe ✓
• nom_departement → dépend de id_departement ✗ dépendance transitive !
• localisation → dépend de id_departement ✗ dépendance transitive !
EMPLOYE (id_employe, nom, id_departement)
‾‾‾‾‾‾‾‾‾‾
DEPARTEMENT (id_departement, nom_departement, localisation)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾
Les infos du département sont isolées dans leur propre table.
| Forme | Condition supplémentaire | Problème éliminé |
|---|---|---|
1NF |
Attributs atomiques, pas de répétitions | Valeurs multiples dans une cellule |
2NF |
1NF + pas de dépendance partielle à la PK | Redondance sur PK composée |
3NF |
2NF + pas de dépendance transitive | Redondance entre colonnes non-clés |
BCNF |
3NF + tout déterminant est une super-clé | Anomalies résiduelles (cas rare) |
En pratique, atteindre la 3NF suffit pour la grande majorité des projets. Un bon MCD bien conçu produit un MLD déjà en 3NF.
Le diagramme de classes UML est une alternative à MERISE pour modéliser une base de données. Il est plus répandu dans les contextes orientés objet (Java, C#, PHP…). Les classes UML se transforment en tables de la même façon que les entités MERISE.
| MERISE | UML |
|---|---|
| Entité | Classe |
| Attribut | Attribut de classe (avec type) |
Identifiant # | Attribut marqué «PK» ou souligné |
| Association | Association / Agrégation / Composition |
| Cardinalités (0,n) / (1,1) | Multiplicités * / 1 — notées aux extrémités du lien |
| UML | MERISE équivalent | Signification |
|---|---|---|
1 | (1,1) | Exactement un |
0..1 | (0,1) | Zéro ou un |
* ou 0..* | (0,n) | Zéro ou plusieurs |
1..* | (1,n) | Un ou plusieurs |
2..5 | — | Entre 2 et 5 (UML plus précis) |
┌────────────────────────┐ ┌────────────────────────┐
│ Client │ │ Commande │
├────────────────────────┤ ├────────────────────────┤
│ «PK» id : int │1 * │ «PK» id : int │
│ nom : string ├─────────┤ dateCommande : date │
│ prenom : string │ │ statut : string │
│ email : string │ │ montantTotal : decimal │
│ telephone : string │ └───────────┬────────────┘
└────────────────────────┘ │ *
(contient)
│ 1..*
┌────────────────────────┐ ┌───────────┴────────────┐
│ Categorie │ │ Produit │
├────────────────────────┤ ├────────────────────────┤
│ «PK» id : int │1 * │ «PK» id : int │
│ libelle : string ├─────────┤ designation : string │
│ description : string │ │ prixUnitaire : decimal │
└────────────────────────┘ │ stock : int │
└────────────────────────┘
Relation Commande ↔ Produit (N:N) :
→ Classe d'association LigneCommande { quantite, remise }
| Type de lien | Notation | Signification BDD |
|---|---|---|
| Association | A ────── B |
Relation simple → FK ou table de jonction |
| Agrégation | A ◇────── B |
B fait partie de A mais peut exister seul → FK nullable |
| Composition | A ◆────── B |
B ne peut exister sans A → FK NOT NULL + ON DELETE CASCADE |
| Héritage | A ────▷ B |
3 stratégies : table unique, une table par classe, une table par classe concrète |
Besoin : Gérer les emprunts d'une bibliothèque. Un adhérent peut emprunter plusieurs livres. Un livre peut être emprunté plusieurs fois mais par un seul adhérent à la fois. Un livre appartient à une ou plusieurs catégories.
┌─────────────────────┐ ┌─────────────────────┐
│ ADHERENT │ │ CATEGORIE │
├─────────────────────┤ ├─────────────────────┤
│ #id_adherent │ │ #id_categorie │
│ nom │ │ libelle │
│ prenom │ └──────────┬──────────┘
│ email │ │ 0,n
│ date_inscription │ CLASSIFIER
└──────────┬──────────┘ │ 1,n
│ 0,n ┌─────────┴──────────┐
EMPRUNTER │ LIVRE │
(date_emprunt, ├─────────────────────┤
date_retour_prevue, │ #isbn │
date_retour_reelle) │ titre │
│ 0,1 │ auteur │
┌──────────┴──────────┐ │ annee_publication │
│ EXEMPLAIRE │ │ disponible │
├─────────────────────┤ └──────────┬──────────┘
│ #id_exemplaire │ 1,n AVOIR 1,1 │
│ etat ├───────────────────────┘
└─────────────────────┘
ADHERENT (id_adherent, nom, prenom, email, date_inscription)
‾‾‾‾‾‾‾‾‾‾‾‾‾
CATEGORIE (id_categorie, libelle)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾
LIVRE (isbn, titre, auteur, annee_publication, disponible)
‾‾‾‾‾‾‾‾
LIVRE_CATEGORIE (isbn, id_categorie) ← table de jonction N:N
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
└─ #isbn référence LIVRE(isbn)
└─ #id_categorie référence CATEGORIE(id_categorie)
EXEMPLAIRE (id_exemplaire, etat, #isbn)
‾‾‾‾‾‾‾‾‾‾‾‾‾‾
└─ #isbn référence LIVRE(isbn)
EMPRUNT (id_exemplaire, id_adherent, date_emprunt,
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
date_retour_prevue, date_retour_reelle)
PK composée : (id_exemplaire, id_adherent, date_emprunt)
└─ #id_exemplaire référence EXEMPLAIRE(id_exemplaire)
└─ #id_adherent référence ADHERENT(id_adherent)
CREATE TABLE adherent (
id_adherent INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(100) NOT NULL,
prenom VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
date_inscription DATE NOT NULL DEFAULT (CURRENT_DATE)
);
CREATE TABLE categorie (
id_categorie INT PRIMARY KEY AUTO_INCREMENT,
libelle VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE livre (
isbn CHAR(13) PRIMARY KEY,
titre VARCHAR(255) NOT NULL,
auteur VARCHAR(255) NOT NULL,
annee_publication YEAR,
disponible TINYINT(1) NOT NULL DEFAULT 1
);
CREATE TABLE livre_categorie (
isbn CHAR(13) NOT NULL,
id_categorie INT NOT NULL,
PRIMARY KEY (isbn, id_categorie),
FOREIGN KEY (isbn) REFERENCES livre(isbn)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (id_categorie) REFERENCES categorie(id_categorie)
ON DELETE RESTRICT ON UPDATE CASCADE
);
CREATE TABLE exemplaire (
id_exemplaire INT PRIMARY KEY AUTO_INCREMENT,
etat ENUM('bon','use','abime') NOT NULL DEFAULT 'bon',
isbn CHAR(13) NOT NULL,
FOREIGN KEY (isbn) REFERENCES livre(isbn)
ON DELETE RESTRICT ON UPDATE CASCADE
);
CREATE TABLE emprunt (
id_exemplaire INT NOT NULL,
id_adherent INT NOT NULL,
date_emprunt DATE NOT NULL,
date_retour_prevue DATE NOT NULL,
date_retour_reelle DATE,
PRIMARY KEY (id_exemplaire, id_adherent, date_emprunt),
FOREIGN KEY (id_exemplaire) REFERENCES exemplaire(id_exemplaire)
ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY (id_adherent) REFERENCES adherent(id_adherent)
ON DELETE RESTRICT ON UPDATE CASCADE
);
Aucun résultat pour votre recherche.