Ave,

Prenons le cas du MCD ci-dessous, reprenant celui de la figure 13.39 de l’ouvrage de D. Nanci et B. Espinasse Ingénierie des systèmes d'information - Merise deuxième génération (paragraphe III-C-3-ac. Contraintes d’inclusion de relations sur d’autres relations) :

Figure 1

Code SQL produit par Looping :

Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
CREATE TABLE Enseignant(
   eno SMALLINT,
   PRIMARY KEY(eno)
);
CREATE TABLE Matiere(
   mno SMALLINT,
   PRIMARY KEY(mno)
);
CREATE TABLE Classe(
   cno INT,
   PRIMARY KEY(cno)
);
CREATE TABLE SaitEnseigner(
   eno SMALLINT,
   mno SMALLINT,
   PRIMARY KEY(eno, mno),
   FOREIGN KEY(eno) REFERENCES Enseignant(eno),
   FOREIGN KEY(mno) REFERENCES Matiere(mno)
);
CREATE TABLE Enseigne(
   eno SMALLINT,
   mno SMALLINT,
   cno INT,
   PRIMARY KEY(eno, mno, cno),
   FOREIGN KEY(eno) REFERENCES Enseignant(eno),
   FOREIGN KEY(mno) REFERENCES Matiere(mno),
   FOREIGN KEY(cno) REFERENCES Classe(cno)
);

Transformons les associations SaitEnseigner et Enseigne en entités-types. Le MCD devient :


Figure 2

Le LDD est inchangé.

Remplaçons les associations E_E et E_M par une association E_S en sorte que Enseigne devienne une entité-type faible relativement à SaitEnseigner. Le MCD devient :

Figure 3

Le LDD évolue très légèrement : en remplacement des clés étrangères référençant les tables Enseignant et Matiere, la table Enseigne est dotée d’une clé étrangère faisant référence à la clé primaire de la table SaitEnseigner. Noter que dans le cas de certains SGBD, SQL Server par exemple, cela pourrait être une référence à toute autre clé candidate définie pour cette table.

Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CREATE TABLE Enseignant(
   eno SMALLINT,
   PRIMARY KEY(eno)
);
CREATE TABLE Matiere(
   mno SMALLINT,
   PRIMARY KEY(mno)
);
CREATE TABLE Classe(
   cno SMALLINT,
   PRIMARY KEY(cno)
);
CREATE TABLE SaitEnseigner(
   mno SMALLINT,
   eno SMALLINT,
   PRIMARY KEY(mno, eno),
   FOREIGN KEY(mno) REFERENCES Matiere(mno),
   FOREIGN KEY(eno) REFERENCES Enseignant(eno)
);
CREATE TABLE Enseigne(
   mno SMALLINT,
   eno SMALLINT,
   cno SMALLINT,
   PRIMARY KEY(mno, eno, cno),
   FOREIGN KEY(mno, eno) REFERENCES SaitEnseigner(mno, eno),
   FOREIGN KEY(cno) REFERENCES Classe(cno)
);

Observons ceci :

La contrainte d’inclusion entre les associations Enseigne et SaitEnseigner fait que la table Enseigne de clé primaire (ou alternative) {cno, mno, eno} implique la table SaitEnseigner de clé primaire (ou alternative) {mno, eno}. Dans ces conditions la paire Enseigne{mno, eno} est incluse dans SaitEnseigner{mno, eno}, ce que symbolise la contrainte CM1 :

(CM1)      Enseigne{mno, eno} ⊆ SaitEnseigner{mno, eno}

Par projection (propriété de l’algèbre relationnelle), il existe une contrainte CM2 :

(CM2)      Enseigne{mno} ⊆ SaitEnseigner{mno}

Intégrité référentielle oblige, il existe une contrainte CM3 :

(CM3)      SaitEnseigner{mno} ⊆ Matiere{mno}

Et par transitivité

(CM4)      Enseigne{mno} ⊆ SaitEnseigner{mno} ⊆ Matiere{mno}

=>

(CM5)      Enseigne{mno} ⊆ Matiere{mno}

Ainsi, l’association initiale E_M (figure 2) n’est pas perdue.

Ce qui vaut pour les matières vaut pour les enseignants.

Par projection, de la contrainte CM1 sur {eno}, on produit une contrainte CE1 :

(CE1)      Enseigne{eno} ⊆ SaitEnseigner{eno}

Intégrité référentielle oblige, il existe une contrainte CE2 :

(CE2)       SaitEnseigner{eno} ⊆ Enseignant{eno}

Et par transitivité

(CE3)      Enseigne{eno} ⊆ SaitEnseigner{eno} ⊆ Enseignant{eno}

=>

(CE4)      Enseigne{eno} ⊆ Enseignant{eno}

Ainsi, l’association initiale E_E (figure 2) n’est pas perdue.

Les associations E_M et E_E étant préservées, non seulement le code SQL obtenu à partir du MCD de la figure 3 peut remplacer le code SQL obtenu à partir du MCD de la figure 1, mais en outre il n’est nul besoin de mettre en oeuvre un quelconque trigger. 

-------------------------

Si l’association SaitEnseigner n’était plus binaire, ça coincerait. Exemple :

Figure 4

En effet, transformons les associations SaitEnseigner et Enseigne en entités-types :


Figure 5

Puis remplaçons les associations E_E et E_M par l’ association E_S faisant que Enseigne devient une entité-type faible relativement à SaitEnseigner. Le MCD devient :

Figure 6

Le code SQL correspondant :

Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
CREATE TABLE Enseignant(
   eno SMALLINT,
   PRIMARY KEY(eno)
);
CREATE TABLE Matiere(
   mno SMALLINT,
   PRIMARY KEY(mno)
);
CREATE TABLE Classe(
   cno SMALLINT,
   PRIMARY KEY(cno)
);
CREATE TABLE SaitEnseigner(
   mno SMALLINT,
   eno SMALLINT,
   LaDate DATE,
   PRIMARY KEY(mno, eno, LaDate),
   FOREIGN KEY(mno) REFERENCES Matiere(mno),
   FOREIGN KEY(eno) REFERENCES Enseignant(eno)
);
CREATE TABLE Enseigne(
   mno SMALLINT,
   eno SMALLINT,
   LaDate DATE,
   cno SMALLINT,
   PRIMARY KEY(mno, eno, LaDate, cno),
   FOREIGN KEY(mno, eno, LaDate) REFERENCES SaitEnseigner(mno, eno, LaDate),
   FOREIGN KEY(cno) REFERENCES Classe(cno)
);

Etant donné que, sauf dans le cas des clés étrangères, les SGBD SQL ne permettent pas de traiter des contraintes de base de données (contraintes entre tables) autrement que par le biais des triggers, ici on est refait.  

Autrement dit, pour que Looping puisse traiter des contraintes d’inclusion au stade SQL, il doit se limiter au cas où l’association cible d’une telle contrainte (SaitEnseigner en l’occurrence) n’est pas porteuse d’une patte la connectant à une entité-type (Depuis en l’occurrence) dont l’identifiant participe à l’identification de l’association cible de la contrainte (SaitEnseigner).

En passant, il n’y a pas de problème avec le Modèle Relationnel de Données puisque les contraintes entre tables y sont parfaitement légales  :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
VAR SaitEnseigner BASE RELATION {mno INT, eno INT, LaDate CHAR} KEY{mno, eno, LaDate} ;
VAR Enseigne  BASE RELATION {mno INT, eno INT, cno INT} KEY{mno, eno, cno} ;

CONSTRAINT Enseigne_FK Enseigne{mno, eno} ⊆ SaitEnseigner{mno, eno} ;
Rappel. J’ai traité par ailleurs des contraintes d’inclusion dans le cas des cardinalité 0,1.

(a) patte portée par l’association cible de la contrainte (cf. Contraintes d'inclusion (du MCD au code SQL))

(b) patte portée par l’association source de la contrainte (cf. Looping version 4.1 disponible (avec Rétroconception), post #44)

Si vous avec connaissance d’autres types de cas où interviennent les contraintes d’inclusion, merci de me les proposer !

François