Le modèle logique d'une base de données relationnelle est l'ensemble de ses tables.
Pour chaque table, on spécifie :
- Un nom.
- Le nom des colonnes.
- Les contraintes de clés primaires et étrangères.
👉 Nous ne spécifions pas les types de colonnes, ni les contraintes d'intégrité, sauf pour les clés primaires et étrangères.
Dériver un modèle logique d'un modèle conceptuel
Des règles existent pour dériver un modèle logique à partir du modèle conceptuel.
Nous expliquons ces règles sur le modèle conceptuel présenté dans la figure ci-dessous.
Règles pour les entités
- Chaque entité du modèle conceptuel devient une table dans le modèle logique.
- Une table a une colonne pour chaque attribut de l'entité correspondante.
- La clé primaire d'une table est constituée des colonnes qui sont dérivées des attributs soulignés de l'entité correspondante. Les attributs soulignés dans un modèle conceptuel sont ceux qui identifient de manière unique une entité.
Revenons à notre exemple
Puisque nous avons quatre entités, nous obtenons quatre tables.
👉 Les colonnes soulignées d'une table constituent la clé primaire de celle-ci.
segment | (seg_id, seg_color) |
point | (x, y, p_color) |
label | (label_id, label_text, font_size, font_color) |
polygon | (pol_id) |
Règles pour les associations one-to-many
Chaque association a des cardinalités (min, max)
pour chaque entité impliquée dans l'association (voir ici pour plus de détails).
Une association one-to-many est une association dont la cardinalité maximale est 1 d'un côté et n
de l'autre.
Soit une association one-to-many, nous modifions le modèle logique de la manière suivante :
- Dans la table correspondant à l'entité du côté 1 de l'association, nous créons une colonne pour chaque attribut souligné de l'entité du côté
n
de l'association. - L'ensemble de ces colonnes est une clé étrangère.
Revenons à notre exemple
Les deux associations has_endpoint
sont de type one-to-many. Considérons l'une de ces associations.
- Nous créons dans la table
segment
(du côté 1 de l'association) deux nouvelles colonnesx1
,y1
(correspondant aux deux attributs soulignés de l'entité du côtén
). {x1, y1}
est une clé étrangère référençant les colonnes{x, y}
de la tablepoint
.
Nous suivons le même raisonnement avec la deuxième association has_endpoint
.
- Nous créons dans la table
segment
(du côté 1 de l'association) deux nouvelles colonnesx2
,y2
(correspondant aux deux attributs soulignés de l'entité du côtén
). {x2, y2}
est une clé étrangère référençant les colonnes{x, y}
de la tablepoint
.
Nous mettons à jour le schéma logique. Les nouveaux éléments sont en gras.
👉 La notation T(a, b)
, utilisée dans la spécification des clés étrangères ci-dessous, désigne les colonnes a
, b
de la table T
.
segment | (seg_id, seg_color, x1, y1, x2, y2) |
point | (x, y, p_color) |
label | (label_id, label_text, font_size, font_color) |
polygon | (pol_id) |
Foreign keys:
segment(x1, y1)
referencespoint(x, y)
segment(x2, y2)
referencespoint(x, y)
Règles pour les associations one-to-one
Une association one-to-one est une association dont la cardinalité maximale est de 1 des deux côtés. Il s'agit d'un cas particulier d'association one-to-many.
Revenons à notre exemple
Considérons l'association has_label
entre segment
et label
.
Nous avons deux possibilités :
1. Nous créons une nouvelle colonne label_id
dans la table segment
.
2. Nous créons une nouvelle colonne seg_id
dans la table label
.
Si nous choisissons la première option, nous pourrions avoir des valeurs NULL dans la colonne label_id
parce qu'un segment peut ne pas avoir d'étiquette.
Cependant, la deuxième option serait pire.
En fait, si nous suivons la même logique pour les autres associations has_label
(celle entre point
et label
, et celle entre polygon
et label
), nous nous retrouverons avec trois colonnes dans la table label
: seg_id
, polygon_id
et point_id
. Puisqu'une étiquette est attachée soit à un point, soit à un segment, soit à un polygone, nous aurions également des valeurs NULL avec cette solution.
En fait, nous aurions plus de valeurs NULL qu'avec la première solution.
👉 Choisissez l'option qui minimise les risques d'avoir des valeurs NULL.
Nous mettons à jour le schéma logique. Les nouveaux éléments sont en gras.
segment | (seg_id, seg_color, x1, y1, x2, y2, label_id) |
point | (x, y, p_color, label_id) |
label | (label_id, label_text, font_size, font_color) |
polygon | (pol_id, label_id) |
Foreign keys:
segment(x1, y1)
referencespoint(x, y)
segment(x2, y2)
referencespoint(x, y)
segment(label_id)
referenceslabel(label_id)
point(label_id)
referenceslabel(label_id)
polygon(label_id)
referenceslabel(label_id)
Règles pour les associations many-to-many
Une association many-to-many est une association dont la cardinalité maximale est n
des deux côtés.
👉 Une association many-to-many devient une table dans le modèle logique.
Les colonnes de cette nouvelle table sont :
- Tous les attributs soulignés des deux entités impliquées dans l'association. Ces attributs combinés forment la clé primaire de la nouvelle table.
- Tous les attributs de l'association.
Revenons à notre exemple
L'association has_side
est une association many-to-many. Nous créons une nouvelle table side
(notez que le nom d'une table est généralement un nom propre) avec les colonnes suivantes : seg_id
(attribut souligné de l'entité segment
), pol_id
(attribut souligné de l'entité polygon
), index
(attribut de l'association).
{seg_id, pol_id}
est la clé primaire de la tableside
.seg_id
etpol_id
sont des clés étrangères, référençant respectivement les colonnesseg_id
de la tablesegment
etpol_id
de la tablepolygon
.
Nous mettons à jour le schéma logique. Les nouveaux éléments sont en gras.
segment | (seg_id, seg_color, x1, y1, x2, y2, label_id) |
point | (x, y, p_color, label_id) |
label | (label_id, label_text, font_size, font_color) |
polygon | (pol_id, label_id) |
side | (seg_id, pol_id, index) |
Foreign keys:
segment(x1, y1)
referencespoint(x, y)
segment(x2, y2)
referencespoint(x, y)
segment(label_id)
referenceslabel(label_id)
point(label_id)
referenceslabel(label_id)
polygon(label_id)
referenceslabel(label_id)
side(seg_id)
referencessegment(seg_id)
side(pol_id)
referencespolygon(pol_id)
👉 Lorsqu'une table a une clé primaire composite (une table avec plusieurs colonnes), il est possible, voire recommandé, de créer une colonne fictive dont les valeurs identifient de manière unique une ligne de la table et qui est choisie comme clé primaire.
Dans notre exemple, nous pouvons créer une colonne side_id
dans la table side
et l'utiliser comme clé primaire.