Contraintes d'inclusion (du MCD au code SQL)
Prenons le cas du MCD ci-dessous, reprenant celui de la figure 13.38 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-aa. Inclusion de participations d'une entité à plusieurs relations (INCLUSION)) :
La contrainte à garantir est la suivante :
(C1) Une personne ne peut effectuer un prêt qu’à la condition d’avoir préalablement souscrit un abonnement.
Cette contrainte fait l’objet dans le MCD ci-dessus d’une contrainte d’inclusion connectant les associations Souscrire et Effectuer.
La cardinalité 0,1 portée par la patte connectant l’entité-type Personne et l’association Souscrire oblige à mettre en oeuvre la contrainte d’inclusion. Si la cardinalité avait été 1,1, toute personne aurait obligatoirement souscrit un abonnement, la contrainte (C1) aurait donc automatiquement été vérifiée, et il eut été inutile dans ces conditions de mettre en oeuvre une contrainte d’inclusion.
Passage à SQL. Pour garantir la contrainte au stade SQL, dans leur ouvrage les auteurs mettent en oeuvre une instruction CREATE ASSERTION, mais comme les SGBD SQL du marché ne la proposent pas, leur palliatif passe par une instruction CREATE TRIGGER. Sachant que cette instruction diffère sensiblement d’un éditeur à l’autre et qu’elle est pénible à coder (je plains les auteurs), le défi est de produire un code SQL garantissant la contrainte autrement qu’avec un trigger.
La proposition des auteurs, avec trigger.
En l’absence d’un LDD, prenons celui produit par Looping :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| CREATE TABLE Abonnement(
abno INT,
CONSTRAINT Abonnement_PK PRIMARY KEY(abno)
);
CREATE TABLE Personne(
psno INT,
abno INT,
CONSTRAINT Personne_PK PRIMARY KEY(psno),
CONSTRAINT Personne_Abonnement_FK FOREIGN KEY(abno) REFERENCES Abonnement(abno) ON DELETE CASCADE
);
CREATE TABLE Pret(
prno INT,
psno INT NOT NULL,
CONSTRAINT Pret_PK PRIMARY KEY(prno),
CONSTRAINT Pret_Personne_FK FOREIGN KEY(psno) REFERENCES Personne(psno) ON DELETE CASCADE
); |
Où l’on note que la colonne abno de la table Personne est dotée du marqueur NULL. 
Le trigger (ORACLE) reprenant celui des auteurs (colonnes renommées) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| CREATE TRIGGER Inclusion_Effectuer_Souscrire
BEFORE INSERT ON Pret
ON EACH ROW
WHEN new.psno IS NOT NULL
DECLARE
nb_abonnement number;
BEGIN
SELECT COUNT(*) INTO nb_abonnement
FROM Personne
WHERE psno = :new.psno ;
IF nb_abonnement = 0 THEN
raise_application_error (-20006, 'Un abonnement n'a pas été souscrit');
END IF;
END; |
Une solution pour éviter la présence du bonhomme NULL et la mise en oeuvre du trigger est de passer par le MCD suivant :

Code SQL produit par Looping :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| CREATE TABLE Personne(
psno SMALLINT,
CONSTRAINT Personne_PK PRIMARY KEY(psno)
);
CREATE TABLE Abonnement(
abno SMALLINT,
CONSTRAINT Abonnement_PK PRIMARY KEY(abno)
);
CREATE TABLE Souscrire(
psno SMALLINT,
abno SMALLINT NOT NULL,
CONSTRAINT Souscrire_PK PRIMARY KEY(psno),
CONSTRAINT Souscrire_Personne_FK FOREIGN KEY(psno) REFERENCES Personne(psno) ON DELETE CASCADE,
CONSTRAINT Souscrire_Abonnement_FK FOREIGN KEY(abno) REFERENCES Abonnement(abno) ON DELETE CASCADE
);
CREATE TABLE Pret(
prno INT,
psno SMALLINT NOT NULL,
CONSTRAINT Pret_PK PRIMARY KEY(prno),
CONSTRAINT Pret_Souscrire_FK FOREIGN KEY(psno) REFERENCES Souscrire(psno) ON DELETE CASCADE
); |
Ce LDD ne comporte pas de trigger, ouf ! Reconnaissons que le MCD de la figure 1 est, sémantiquement parlant, plus séduisant que celui de la figure 2, mais peu importe ici. Le second MCD implique-t-il le premier ? Oui, si l’on est à même de passer automatiquement du premier au second.
Passage de la figure 1 à la figure 2
Osons nous mettre à la place de Looping. Dans le MCD de la figure 1, on détecte donc une contrainte d'inclusion. Celle-ci a pour source l’association Effectuer, pour cible l’association Souscrire, et pour pivot l’entité-type Personne. La patte connectant l’association (Souscrire) et le pivot (Personne) est porteuse d’une association 0,1 : suspicion ! 
Dans cette situation, on peut proposer une méthode pour passer du premier MCD au second :
Remplacer l’association cible Souscrire par une entité-type (Souscrire) à connecter à la source (Effectuer). La patte de la connexion est à faire porter d’une cardinalité identique à celle portée par la patte connectant le pivot (Personne) et la source (Effectuer) : il s’agit en l’occurrence d’une cardinalité 0,n. A cet effet, Looping donne le moyen de transformer l’association Souscrire en entité-type :
=>
Il reste à faire pivoter la patte d’association connectant Effectuer et Personne pour qu’elle associe Effectuer et Souscrire (au passage on efface la contrainte d’inclusion rendue inutile).
Au résultat :
Pour détailler
1) Looping a transformé l’association cible Souscrire de la figure 1 en entité-type (Souscrire).
2 Looping a créé une association S_P, connectant les entités-types Souscrire et Personne. La cardinalité portée par la patte connectant Personne et S_P est celle portée par la patte connectant le pivot et la cible dans la figure 1, c’est-à-dire 0,1. La patte connectant Souscrire et S_P est rendue porteuse par Looping d’une cardinalité 1,1(R), en sorte que cette entité-type hérite de l’identifiant du pivot Personne.
3) Looping a créé une association S_A, connectant les entités-types Souscrire et Abonnement. La cardinalité portée par la patte connectant Abonnement et l’association S_A est celle portée par la patte connectant Souscrire et Abonnement dans la figure 1. La cardinalité portée par la patte connectant Souscrire et l’association S_A est forcément 1,1 (une personne ne souscrit qu’un seul abonnement).
A partir du nouveau MCD, on produit le code SQL présenté ci-dessus, suite à quoi, ce MCD ayant rempli sa mission, il disparaît.
Conclusion
Soit on adopte la méthode Nanci (page 304 de l’ouvrage cité) et l'on doit créer le trigger (pas très jojo) en fonction de son propre SGBD, soit on demande à Looping de produire directement le code SQL qui va bien (pas de trigger), selon la méthode qui vient d’être proposée. C’est vous qui voyez.
Partager