CentraleSupélecDépartement informatique
Plateau de Moulon
3 rue Joliot-Curie
F-91192 Gif-sur-Yvette cedex
Modèle logique d'une base de données relationnelle

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.


Modèle conceptuel pour une base de données pour de formes géométriques.

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 colonnes x1, 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 table point.

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 colonnes x2, 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 table point.

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) references point(x, y)
  • segment(x2, y2) references point(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) references point(x, y)
  • segment(x2, y2) references point(x, y)
  • segment(label_id) references label(label_id)
  • point(label_id) references label(label_id)
  • polygon(label_id) references label(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 table side.
  • seg_id et pol_id sont des clés étrangères, référençant respectivement les colonnes seg_id de la table segment et pol_id de la table polygon.

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) references point(x, y)
  • segment(x2, y2) references point(x, y)
  • segment(label_id) references label(label_id)
  • point(label_id) references label(label_id)
  • polygon(label_id) references label(label_id)
  • side(seg_id) references segment(seg_id)
  • side(pol_id) references polygon(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.