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

Restricciones de clave externa:cuándo usar ON UPDATE y ON DELETE

No dude en poner restricciones en la base de datos. Se asegurará de tener una base de datos consistente, y esa es una de las buenas razones para usar una base de datos. Especialmente si tienes varias aplicaciones solicitándolo (o solo una aplicación pero con un modo directo y un modo por lotes usando diferentes fuentes).

Con MySQL no tiene restricciones avanzadas como las que tendría en PostgreSQL, pero al menos las restricciones de clave externa son bastante avanzadas.

Tomaremos un ejemplo, una tabla de empresa con una tabla de usuario que contiene personas de esta empresa

CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

Veamos la ACTUALIZACIÓN cláusula:

  • EN RESTRINGIR ACTUALIZAR :el predeterminado :si intenta actualizar un company_id en la tabla EMPRESA, el motor rechazará la operación si al menos un USUARIO se vincula a esta empresa.
  • EN ACTUALIZAR SIN ACCIÓN :igual que RESTRINGIR.
  • EN CASCADA DE ACTUALIZACIÓN :el mejor por lo general :si actualiza un company_id en una fila de la tabla EMPRESA, el motor lo actualizará en consecuencia en todas las filas de USUARIO que hacen referencia a esta EMPRESA (pero no se activaron activadores en la tabla de USUARIO, advertencia). El motor rastreará los cambios por usted, es bueno.
  • EN ACTUALIZAR ESTABLECER NULO :si actualiza un company_id en una fila de la tabla EMPRESA, el motor establecerá los USUARIOS relacionados company_id en NULL (debe estar disponible en el campo USER company_id). No veo nada interesante que hacer con eso en una actualización, pero puedo estar equivocado.

Y ahora en ON DELETE lado:

  • ACTIVAR ELIMINAR RESTRINGIR :el predeterminado :si intenta eliminar un ID de company_id en la tabla EMPRESA, el motor rechazará la operación si al menos un USUARIO se vincula a esta empresa, puede salvarle la vida.
  • SIN ELIMINAR SIN ACCIÓN :igual que RESTRINGIR
  • EN ELIMINAR CASCADA :peligroso :si elimina una fila de empresa en la tabla EMPRESA, el motor también eliminará los USUARIOS relacionados. Esto es peligroso, pero se puede usar para realizar limpiezas automáticas en tablas secundarias (por lo que puede ser algo que desee, pero ciertamente no para un ejemplo de EMPRESA <->USUARIO)
  • EN ELIMINAR ESTABLECER NULO :puñado :si elimina una fila de EMPRESA, los USUARIOS relacionados tendrán automáticamente la relación con NULL. Si Nulo es su valor para los usuarios sin compañía, esto puede ser un buen comportamiento, por ejemplo, tal vez necesite mantener a los usuarios en su aplicación, como autores de algún contenido, pero eliminar la compañía no es un problema para usted.

normalmente mi opción predeterminada es:ON ELIMINAR RESTRINGIR ON ACTUALIZAR CASCADA . con algo de ON DELETE CASCADE para tablas de seguimiento (registros, no todos los registros, cosas así) y ON DELETE SET NULL cuando la tabla maestra es un 'atributo simple' para la tabla que contiene la clave externa, como una tabla JOB para la tabla USER.

Editar

Ha pasado mucho tiempo desde que escribí eso. Ahora creo que debería agregar una advertencia importante. MySQL tiene una gran limitación documentada con las cascadas. Las cascadas no disparan disparadores . Entonces, si tenía suficiente confianza en ese motor para usar activadores, debería evitar las restricciones en cascada.

==> Vea a continuación la última edición, las cosas se están moviendo en este dominio

Y no creo que esto se arregle algún día. Las restricciones de clave externa son administradas por el almacenamiento de InnoDb y los Triggers son administrados por el motor MySQL SQL. Ambos están separados. Innodb es el único almacenamiento con administración de restricciones, tal vez algún día agreguen disparadores directamente en el motor de almacenamiento, tal vez no.

Pero tengo mi propia opinión sobre qué elemento debe elegir entre la mala implementación del disparador y el muy útil soporte de restricciones de claves externas. Y una vez que se acostumbre a la coherencia de la base de datos, le encantará PostgreSQL.

12/2017-Actualizando esta edición sobre MySQL:

como dice @IstiaqueAhmed en los comentarios, la situación ha cambiado en este tema. Así que siga el enlace y verifique la situación real actualizada (que puede cambiar nuevamente en el futuro).