Mysql
 sql >> Database >  >> RDS >> Mysql

Chiave esterna a più colonne:imposta la singola colonna su Null ON DELETE anziché su tutto

Dopo alcune ricerche sembra che quel particolare requisito non sia implementabile utilizzando chiavi esterne.

La soluzione migliore sembra utilizzare un mix di Chiavi Estere e un Trigger .

Il problema può essere risolto per l'esempio fornito dalle seguenti affermazioni:

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;

Nota che "ON DELETE CASCADE" dell'ultima chiave esterna non porterà mai a un'eliminazione a cascata poiché il trigger ha già rimosso i riferimenti di chiave esterna annullando le righe corrispondenti.

Aggiunta:invece di usare "ON DELETE CASCADE" si potrebbe usare "ON DELETE SET NULL" con lo stesso trigger, ma poi "lectureId" deve essere nullable e uno dovrebbe includere un "CHECK (lectureId IS NOT NULL)" per assicurarti che non sia mai impostato su null