una tabla solucion restricción referencia quitar que puede primaria objeto línea llave hay función foreign foranea falla extranjera externa error eliminar deletar datos cuál constraint clave mysql sql foreign-keys sql-delete

mysql - solucion - Eliminar de varias tablas con restricciones externas



no se puede quitar el objeto hay una referencia a él en una restricción foreign key (4)

Estoy tratando de eliminar de varias tablas. Así es como se ven mis mesas

A_has_B ---- B ---- C_has_B (many to many) (many to many)

Estoy tratando de eliminar todas las filas de A_has_B, B y C_has_B dado el ID de un registro en B. Estoy usando MySQL con el motor de almacenamiento innodb con claves externas definidas para A_has_B y C_has_B haciendo referencia a los ID en B.

Estoy tratando de realizar mi eliminación de la siguiente manera:

DELETE A_has_B.*, C_has_B.*, B.* FROM A join B on (B.B_id = A.B_id) join C on (C.B_id = B.B_id) where B.B_id IN(1,2, 4);

El problema es que cuando ejecuto la consulta, mysql se queja:

Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`db`.`C`, CONSTRAINT `fk_C` FOREIGN KEY (`B_id`) REFERENCES `B` (`B_id`) ON DELETE NO ACTION ON UPDATE NO)

¿Cómo puedo arreglar esto?


En realidad, en MySQL, puede desactivar las verificaciones de restricciones de clave externa

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; --your SQL statements SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;

La declaración en la primera línea obliga al servidor MySQL a desactivar las comprobaciones de clave externa y la última línea las vuelve a activar (muy importante). Dos cosas a tener en cuenta:

  • Es bastante peligroso desactivar los controles por restricciones y no es algo que deba hacerse en, por ejemplo, un DB de producción ... la forma más segura es usar sentencias separadas.
  • Siempre vuelva a activar las restricciones

Haga las eliminaciones en estados separados y funcionará.


La forma más sencilla sería eliminar de cada tabla individualmente:

-- Remove all connections from A which reference -- the B-rows you want to remove DELETE FROM A_has_B WHERE B_id IN (1,2,4); -- Remove all connections from C which reference -- the B-rows you want to remove DELETE FROM C_has_B WHERE B_id IN (1,2,4); -- Finally remove the B-rows DELETE FROM B WHERE B_id IN (1,2,4);

MySQL también le permite eliminar de varias tablas en una declaración. Pero no hay manera de controlar el orden de las eliminaciones. Del manual :

Si usa una instrucción DELETE de tablas múltiples que involucra tablas InnoDB para las cuales hay restricciones de clave externa, el optimizador de MySQL podría procesar las tablas en un orden diferente al de su relación padre / hijo. En este caso, la declaración falla y se retrotrae. En su lugar, debe eliminar de una sola tabla y confiar en las capacidades de ON DELETE que proporciona InnoDB para hacer que las otras tablas se modifiquen en consecuencia.


Puede especificar "eliminar cascada" en la clave externa. Cuando elimine la fila principal, el motor mysql eliminará los registros en las tablas secundarias relacionadas