No dude en poner restricciones en la base de datos. Asegúrese de tener una base de datos coherente, y esa es una de las buenas razones para usar una base de datos. Especialmente si tiene varias aplicaciones que lo solicitan (o solo una aplicación pero con un modo directo y un modo por lotes utilizando 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 la compañía de tesis
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 cláusula ON UPDATE :
- RESTRICTO DE ACTUALIZACIÓN : el valor predeterminado : si intenta actualizar un company_id en la tabla EMPRESA, el motor rechazará la operación si un USUARIO al menos se vincula a esta empresa.
- ACTUALIZACIÓN SIN ACCIÓN : igual que RESTRICT.
- EN ACTUALIZACIÓN EN CASCADA : el mejor generalmente : 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 hay activadores activados en la tabla USUARIO, advertencia). El motor hará un seguimiento de los cambios por usted, es bueno.
- ON UPDATE SET NULL : si actualiza un company_id en una fila de la tabla COMPANY, el motor establecerá USERs relacionados company_id en NULL (debe estar disponible en el campo USER company_id). No puedo ver nada interesante que hacer con eso en una actualización, pero puedo estar equivocado.
Y ahora en el lado ON DELETE :
- AL BORRAR RESTRICCIÓN : el valor predeterminado : si intenta eliminar un ID de company_id en la tabla EMPRESA, el motor rechazará la operación si un USUARIO al menos enlaza con esta empresa, puede salvarle la vida.
- AL BORRAR SIN ACCIÓN : igual que RESTRICT
- EN ELIMINAR CASCADA : peligroso : si elimina una fila de la empresa en la tabla EMPRESA, el motor eliminará también a los USUARIOS relacionados. Esto es peligroso, pero puede usarse para realizar limpiezas automáticas en tablas secundarias (por lo que puede ser algo que desee, pero ciertamente no para un ejemplo de COMPAÑÍA <-> USUARIO)
- AL ELIMINAR SET NULL : puñado : si elimina una fila de la EMPRESA, los USUARIOS relacionados tendrán automáticamente la relación con NULL. Si Null es su valor para los usuarios sin compañía, este 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.
generalmente mi valor predeterminado es: AL BORRAR RESTRICCIÓN AL ACTUALIZAR CASCADA . con algunas 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 de TRABAJO 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 cascadas. Las cascadas no son disparadores . Entonces, si tenía suficiente confianza en ese motor para usar disparadores, debería evitar las restricciones en cascada.
Los activadores de MySQL se activan solo para los cambios realizados en las tablas mediante declaraciones SQL. No se activan por cambios en las vistas, ni por cambios en las tablas hechas por API que no transmiten sentencias SQL al servidor MySQL
==> Vea a continuación la última edición, las cosas se están moviendo en este dominio
Los disparadores no se activan mediante acciones de clave externa.
Y no creo que esto se arregle algún día. El almacenamiento de InnoDb gestiona las restricciones de clave externa y el motor MySQL SQL gestiona los disparadores. Ambos están separados. Innodb es el único almacenamiento con gestión de restricciones, quizás algún día agregarán disparadores directamente en el motor de almacenamiento, quizás no.
Pero tengo mi propia opinión sobre qué elemento debe elegir entre la implementación de activación deficiente y el muy útil soporte de restricciones de claves externas. Y una vez que se acostumbre a la consistencia de la base de datos, le encantará PostgreSQL.
12/2017-Actualización de esta edición sobre MySQL:
como lo indicó @IstiaqueAhmed en los comentarios, la situación ha cambiado en este tema. Por lo tanto, siga el enlace y verifique la situación actual actualizada (que puede cambiar nuevamente en el futuro).
ON DELETE CASCADE : dangerous
- Tomar con una pizca de sal.SET NULL
en unaON UPDATE
: la actualización de una empresa representa un destacamento de la Compañía> relación del usuario. Por ejemplo: si una empresa cambia su tipo de negocio, los usuarios anteriores ya no pueden estar relacionados con ese negocio, porNULL
lo tanto, puede ser preferible para este índice.This includes changes to base tables that underlie updatable views
lugar de lo queThey do not activate for changes in views
CASCADE DELETE
generalmente también está bien, incluso se prefiere. No lo considero particularmente peligroso.Además de la respuesta @MarkR: una cosa a tener en cuenta sería que muchos marcos PHP con ORM no reconocerían ni usarían la configuración avanzada de la base de datos (claves foráneas, eliminación en cascada, restricciones únicas), y esto puede provocar un comportamiento inesperado.
Por ejemplo, si elimina un registro utilizando ORM, y
DELETE CASCADE
eliminará registros en tablas relacionadas, el intento de ORM de eliminar estos registros relacionados (a menudo automáticos) dará como resultado un error.fuente
Tendrá que considerar esto en el contexto de la aplicación. En general, debe diseñar una aplicación, no una base de datos (la base de datos simplemente forma parte de la aplicación).
Considere cómo su aplicación debería responder a varios casos.
La acción predeterminada es restringir (es decir, no permitir) la operación, que normalmente es lo que desea, ya que evita errores estúpidos de programación. Sin embargo, en DELETE CASCADE también puede ser útil. Realmente depende de su aplicación y de cómo piensa eliminar objetos particulares.
Personalmente, usaría InnoDB porque no destruye sus datos (consulte MyISAM, que lo hace), en lugar de porque tiene restricciones FK.
fuente