Bonsoir,
mrfof,
Je viens seulement de découvrir votre message, car il ne figure pas dans le forum SCHEMA...
Je réponds quand même, en demandant aux modérateurs que ce message soit transféré dans ce forum.
Capitaine,
Ce qui suit ne concerne que le MCD initial.
mrfof, vous écrivez :
Envoyé par
mrfof
J'ai finalement accepté les NULL pour certains enregistrements de l'association 'Enseigner' qui se transforme en table.
J'aime pas voir ça dans mes table. Pour l'instant c'est le cas.
Null est à chasser d’ici ! Dans un premier temps, vous pouvez produire le MCD suivant :
S’il existe la règle de gestion (RG1) suivante :
(1) Si l'enseignant E enseigne la matière M,
(2) si la matière M est enseignée à la classe C,
(3) si l'enseignant E enseigne dans la classe C,
(4) alors l'enseignants E enseigne la matière M dans la classe C.
Alors on reste là puisque (4) est la conclusion des prémisses (1), (2), (3).
Au stade SQL :
CREATE TABLE MATIERE
(
matiereId INTEGER NOT NULL
, matiereNom VARCHAR(16) NOT NULL
, CONSTRAINT MATIERE_PK PRIMARY KEY (matiereId)
);
CREATE TABLE CLASSE
(
classeId INTEGER NOT NULL
, classeNom VARCHAR(16) NOT NULL
, CONSTRAINT CLASSE_PK PRIMARY KEY (classeId)
);
CREATE TABLE ENSEIGNANT
(
enseignantId INTEGER NOT NULL
, enseignantNom VARCHAR(16) NOT NULL
, CONSTRAINT ENSEIGNANT_PK PRIMARY KEY (enseignantId)
);
CREATE TABLE CM
(
matiereId INTEGER NOT NULL
, classeId INTEGER NOT NULL
, CONSTRAINT CM_PK PRIMARY KEY (matiereId, classeId)
, CONSTRAINT CM_MATIERE_FK FOREIGN KEY(matiereId)
REFERENCES MATIERE (matiereId)
, CONSTRAINT CM_CLASSE_FK FOREIGN KEY (classeId)
REFERENCES CLASSE (classeId)
);
CREATE TABLE EM
(
matiereId INTEGER NOT NULL
, enseignantId INTEGER NOT NULL
, CONSTRAINT EM_PK PRIMARY KEY (matiereId, enseignantId)
, CONSTRAINT EM_MATIERE_FK FOREIGN KEY (matiereId)
REFERENCES MATIERE (matiereId)
, CONSTRAINT EM_ENSEIGNANT_FK FOREIGN KEY (enseignantId)
REFERENCES ENSEIGNANT(enseignantId)
);
CREATE TABLE EC
(
classeId INTEGER NOT NULL
, enseignantId INTEGER NOT NULL
, CONSTRAINT EC_PK PRIMARY KEY (classeId, enseignantId)
, CONSTRAINT EC_CLASSE_FK FOREIGN KEY (classeId)
REFERENCES CLASSE (classeId)
, CONSTRAINT EC_ENSEIGNANT_FK FOREIGN KEY (enseignantId)
REFERENCES ENSEIGNANT (enseignantId)
);
Maintenant, une observation :
En toute logique, un enseignant E ne peut enseigner à une classe C que si la matière M qu’il y enseigne fait partie des matières associées à cette classe.
Pour s’assurer de cela, on peut prévoir le trigger suivant (SQL server en l’occurrence), contrôlant les inserts dans la table EC (prévoir bien sûr le cas des updates) :
CREATE TRIGGER EC_INSERT_TR ON EC AFTER INSERT AS
BEGIN
DECLARE @erreur as INT ;
DECLARE @Engueulade AS VARCHAR(512) ;
SET @erreur =
(
SELECT COUNT(*) FROM
(
SELECT x.classeId, y.matiereId
FROM INSERTED as x
JOIN EM as y on x.enseignantId = y.enseignantId
EXCEPT
SELECT classeId, matiereId
FROM CM
) as truc
)
;
IF @erreur > 0
BEGIN
SET @Engueulade = 'Pour qu''un enseignant enseigne une matière à une classe, '
+ 'il faut d''abord que cette matière concerne cette classe.'
SELECT @Engueulade as ' ', * from INSERTED ;
RAISERROR (@Engueulade, 16,1)
ROLLBACK
END
END
GO
Supposons maintenant que la règle (RG1) n’a pas lieu d’être, c’est-à-dire qu’on peut affecter un enseignant E à une classe C sans tenir compte de l’adéquation des matières qu’il sait enseigner et de celles qui concernent la classe C.
Dans ces conditions, il faut appeler un chat un chat et mettre en oeuvre une association ternaire, appelons-la CME, non pas entre les entités-types CLASSE, MATIERE, ENSEIGNANT, mais entre les associations CM, EM et EC. Etant donné qu’en Merise on n’a pas le droit d’établir d’association entre ces associations, on les déguise en entités-types, avec identification relative (Looping sait parfaitement le faire à notre place) :
Le code SQL précédent est toujours en vigueur, augmenté du CREATE TABLE concernant l’association CME. Les AGL (Looping ici) génèrent ceci :
CREATE TABLE CME
(
classeId INTEGER NOT NULL
matiereId INTEGER NOT NULL
, enseignantId INTEGER NOT NULL
, classeId_1 INTEGER NOT NULL
, matiereId_1 INTEGER NOT NULL
, enseignantId_1 INTEGER NOT NULL
PRIMARY KEY(classeId, matiereId, enseignantId, matiereId_1, classeId_1, enseignantId_1),
FOREIGN KEY(classeId, matiereId) REFERENCES CM(classeId, matiereId),
FOREIGN KEY(enseignantId, matiereId_1) REFERENCES EM(enseignantId, matiereId),
FOREIGN KEY(classeId_1, enseignantId_1) REFERENCES EC(classeId, enseignantId)
);
Code qui doit être débarrassé des attributs redondants classeId_1, matiereId_1, enseignantId_1 :
CREATE TABLE CME
(
classeId INTEGER NOT NULL
, matiereId INTEGER NOT NULL
, enseignantId INTEGER NOT NULL
, CONSTRAINT CME_PK PRIMARY KEY(classeId, matiereId, enseignantId)
, CONSTRAINT CME_CM_FK FOREIGN KEY (matiereId, classeId)
REFERENCES CM (matiereId, classeId)
, CONSTRAINT CME_EM_FK FOREIGN KEY (matiereId, enseignantId)
REFERENCES EM (matiereId, enseignantId)
, CONSTRAINT CME_EC_FK FOREIGN KEY (classeId, enseignantId)
REFERENCES EC (classeId, enseignantId)
);
Partager