Após algumas pesquisas, parece que esse requisito específico não é implementável usando chaves estrangeiras.
A melhor solução parece ser usar uma combinação de Chaves estrangeiras e um Acionador .
O problema pode ser resolvido para o exemplo dado pelas seguintes afirmações:
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;
Observe que o "ON DELETE CASCADE" da última chave estrangeira nunca levará a uma exclusão em cascata, pois o Trigger já removeu as referências de chave estrangeira ao anular as linhas correspondentes.
Adição:Em vez de usar "ON DELETE CASCADE", pode-se usar "ON DELETE SET NULL" com o mesmo gatilho, mas "lectureId" deve ser anulável e deve-se incluir um "CHECK (lectureId IS NOT NULL)" para garantir que nunca seja definido como nulo