Après quelques recherches, il semble que cette exigence particulière ne soit pas implémentable à l'aide de clés étrangères.
La meilleure solution semble être d'utiliser un mélange de clés étrangères et un déclencheur .
Le problème peut être résolu pour l'exemple donné par les instructions suivantes :
CREATE TABLE lectures (
lectureId INT NOT NULL,
title VARCHAR(10) NOT NULL,
PRIMARY KEY (lectureId)
);
CREATE TABLE groups (
lectureId INT NOT NULL,
groupNo INT NOT NULL,
title VARCHAR(10) NOT NULL,
PRIMARY KEY (lectureId,groupNo),
FOREIGN KEY (lectureId) REFERENCES lectures (lectureId)
ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE studentListed (
studentId INT NOT NULL,
lectureId INT NOT NULL,
groupNo INT NULL,
PRIMARY KEY (studentId,lectureId),
FOREIGN KEY (lectureId) REFERENCES lectures (lectureId)
ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (lectureId,groupNo) REFERENCES groups (lectureId,groupNo)
ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TRIGGER GroupDelete BEFORE DELETE ON groups
FOR EACH ROW
UPDATE studentListed SET studentListed.groupNo = NULL
WHERE studentListed.lectureId = OLD.lectureId
AND studentListed.groupNo = OLD.groupNo;
Notez que "ON DELETE CASCADE" de la dernière clé étrangère ne conduira jamais à une suppression en cascade car le déclencheur a déjà supprimé les références de clé étrangère en annulant les lignes correspondantes.
Ajout :Au lieu d'utiliser "ON DELETE CASCADE", on peut utiliser "ON DELETE SET NULL" avec le même déclencheur, mais alors "lectureId" doit être nullable et il faut inclure un "CHECK (lectureId IS NOT NULL)" pour s'assurer qu'il n'est jamais défini sur null