sql >> Base de Datos >  >> RDS >> Mysql

Clave foránea de múltiples columnas:establezca una sola columna en Null ON DELETE en lugar de todo

Después de algunas investigaciones, parece que ese requisito en particular no se puede implementar usando claves externas.

La mejor solución parece ser usar una combinación de claves externas y un Activador .

El problema se puede resolver para el ejemplo dado por las siguientes declaraciones:

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;

Tenga en cuenta que "ON DELETE CASCADE" de la última clave foránea nunca conducirá a una eliminación en cascada ya que el Disparador ya eliminó las referencias de la clave foránea anulando las filas correspondientes.

Adición:en lugar de usar "ON DELETE CASCADE", se podría usar "ON DELETE SET NULL" con el mismo disparador, pero luego "lectureId" tiene que ser anulable y uno debe incluir "CHECK (lectureId IS NOT NULL)" para asegurarse de que nunca se establezca en nulo