Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Mehrfachspalten-Fremdschlüssel:Setzen Sie eine einzelne Spalte auf Null ON DELETE statt auf alle

Nach einiger Recherche scheint es, dass diese bestimmte Anforderung nicht mit Fremdschlüsseln implementiert werden kann.

Die beste Lösung scheint die Verwendung einer Mischung aus Fremdschlüsseln zu sein und einen Trigger .

Das Problem kann für das gegebene Beispiel durch folgende Anweisungen gelöst werden:

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;

Beachten Sie, dass das „ON DELETE CASCADE“ des letzten Fremdschlüssels niemals zu einem kaskadierten Löschen führen wird, da der Trigger die Fremdschlüsselreferenzen bereits entfernt hat, indem er die entsprechenden Zeilen auf Null gesetzt hat.

Zusatz:Anstatt "ON DELETE CASCADE" zu verwenden, könnte man "ON DELETE SET NULL" mit demselben Trigger verwenden, aber dann muss "lectureId" nullable sein und man sollte ein "CHECK (lectureId IS NOT NULL)" einfügen. um sicherzustellen, dass es niemals auf null gesetzt wird