Falla de restricción de clave externa falsa


110

Recibo este mensaje de error:

ERROR 1217 (23000) en la línea 40: No se puede eliminar o actualizar una fila principal: falla una restricción de clave externa

... cuando intento dejar caer una mesa:

DROP TABLE IF EXISTS `area`;

... definido así:

CREATE TABLE `area` (
  `area_id` char(3) COLLATE utf8_spanish_ci NOT NULL,
  `nombre_area` varchar(30) COLLATE utf8_spanish_ci NOT NULL,
  `descripcion_area` varchar(100) COLLATE utf8_spanish_ci NOT NULL,
  PRIMARY KEY (`area_id`),
  UNIQUE KEY `nombre_area_UNIQUE` (`nombre_area`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

Lo curioso es que ya eliminé todas las demás tablas del esquema que tienen claves externas en contra area. En realidad, la base de datos está vacía a excepción de la areatabla.

¿Cómo es posible que tenga filas secundarias si no hay ningún otro objeto en la base de datos? Hasta donde yo sé, InnoDB no permite claves externas en otros esquemas, ¿verdad?

(Incluso puedo ejecutar un RENAME TABLE area TO something_elsecomando: -?)


¿Es posible que la tabla sea parte de una relación de integridad referencial en otro esquema?
Raj More

Tengo otras copias de la aplicación, por lo que siempre es posible. Sin embargo, la sintaxis que utilizo es básicamente CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id), es decir, sin nombre de esquema en la referencia de la tabla: -?
Álvaro González

Respuestas:


101

Dos posibilidades:

  1. Hay una tabla dentro de otro esquema ("base de datos" en terminología de mysql) que tiene una referencia FK
  2. El diccionario de datos interno de innodb no está sincronizado con el de mysql.

Puede ver qué tabla era (una de ellas, de todos modos) haciendo un "MOSTRAR ESTADO INNODB DEL MOTOR" después de que falla la caída.

Si resulta ser el último caso, volcaría y restauraría todo el servidor si puede.

MySQL 5.1 y superior le dará el nombre de la tabla con el FK en el mensaje de error.


1
Ya no puedo reproducir el problema. El diccionario desincronizado se destaca como una razón probable. Lo probaré el día y veré qué SHOW ENGINE INNODB STATUSinformes.
Álvaro González

3
¡Gracias por esta respuesta! Tenía una tabla de muchos a muchos que todavía hacía referencia a la tabla que no podíamos eliminar, así que primero tuve que eliminar esa tabla.
Christian Oudard

5
SHOW ENGINE INNODB STATUS enumera el último error de clave externa en "ÚLTIMO ERROR DE LLAVE EXTRANJERA". Esto tiene una marca de tiempo.
bbrame

podría haber una tabla que todavía tenga una clave de referencia a la tabla de temas. fue en mi caso, así.
RT

Ahorró mucho tiempo. Se eliminó la base de datos debajo de "ÚLTIMO ERROR DE CLAVE EXTRANJERO"
Sand1512

121

A pedido, ahora como respuesta ...

Cuando se utiliza MySQL Query Browser o phpMyAdmin, parece que se abre una nueva conexión para cada consulta ( bugs.mysql.com/bug.php?id=8280 ), por lo que es necesario escribir todas las sentencias de caída en una consulta, por ejemplo.

SET FOREIGN_KEY_CHECKS=0; 
DROP TABLE my_first_table_to_drop; 
DROP TABLE my_second_table_to_drop; 
SET FOREIGN_KEY_CHECKS=1; 

Donde el SET FOREIGN_KEY_CHECKS=1sirve como medida de seguridad extra ...


2
Para aquellos que crean un volcado usando phpMyAdmin, hay una opción "Deshabilitar comprobaciones de claves foráneas" que se agregará automáticamente SET FOREIGN_KEY_CHECKS=0;al comienzo del volcado.
Mike

Parece que phpMyAdmin ha implementado esta hermosa característica, ¡ahora estoy esperando que mysqlWorkbench haga lo mismo! :)
Karlis Rode

@CodeMed FYI, acepté la respuesta de MarkR porque proporciona una explicación del problema que tiene sentido, aunque admito que no pude verificarlo ya que no me he enfrentado a este mismo problema en los 6 años siguientes, ni siquiera una vez. Esta y las respuestas anteriores brindan una solución alternativa (excelente para ese bien) pero en realidad no abordan la pregunta en sí y, dado que solo puede aceptar una respuesta, tuve que elegir.
Álvaro González

1
Advertencia: esta no es una solución, sino solo una solución para un hombre vago. Después de usar esto (con registros en algunas otras tablas que apuntan a la tabla eliminada), experimentará claves externas colgantes que rompen fatalmente la consistencia (la C en ACID ) de su base de datos y sus aplicaciones comenzarán a lanzar excepciones por todas partes. Has sido advertido.
bekce

Aunque estoy seguro de que la advertencia de bekce debe ser entendida y atendida, esta solución funcionó para mí, en una situación en la que estaba seguro de que también estaba eliminando todas las tablas que apuntaban a las tablas con las problemáticas restricciones de clave externa.
user1147171

47

Deshabilitar la verificación de clave externa

SET FOREIGN_KEY_CHECKS=0

62
El comando correcto parece ser SET FOREIGN_KEY_CHECKS=0y soluciona el mensaje de error. ¿Tiene alguna idea de por qué es necesario? ¿Se almacenan en caché las claves externas incluso después de que las tablas se han ido?
Álvaro González

1
Bueno, para decir la verdad, no tengo idea de por qué surge tal problema, pero asegúrese de deshabilitar la verificación de claves cada vez que realice cambios o actualizaciones importantes. Me ha pasado varias veces, dejándome sin dormir durante días.
Flakron Bytyqi

55
¡Asegúrate de hacerlo SET FOREIGN_KEY_CHECKS=1;después de que hayas terminado!
pedro_sland

5
Cuando se utiliza MySQL Query Browser o phpMyAdmin, parece que se abre una nueva conexión para cada consulta ( bugs.mysql.com/bug.php?id=8280 ), por lo que es necesario escribir todas las sentencias de caída en una consulta, por ejemplo. SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; Donde SET FOREIGN_KEY_CHECKS = 1 sirve como una medida de seguridad adicional ...
Karlis Rode

1
@KarlisRode, Bravo por el comentario sobre phpMyAdmin. Si pusieras eso como respuesta, lo haría +1.
Sablefoste

28

de este blog :

Puede deshabilitar temporalmente las comprobaciones de claves externas:

SET FOREIGN_KEY_CHECKS=0;

Solo asegúrese de restaurarlos una vez que haya terminado de jugar:

SET FOREIGN_KEY_CHECKS=1;

Buena respuesta ya que estaba desarrollando en local :)
Adelin

Es una solución alternativa válida (puedo confirmar que funciona) pero la entrada de blog vinculada realmente no habla sobre el escenario en esta pregunta (una base de datos que ya está vacía, excepto para una tabla).
Álvaro González

6

con suerte su trabajo

SET Foreign_key_checks = 0; TABLA DE GOTA table name; SET Foreign_key_checks = 1;


Sí, funciona, como las varias veces que se ha mencionado antes ;-)
Álvaro González

1

En Rails, se puede hacer lo siguiente usando rails console:

connection = ActiveRecord::Base.connection
connection.execute("SET FOREIGN_KEY_CHECKS=0;")

0

Tal vez recibió un error al trabajar con esta tabla antes. Puede cambiar el nombre de la tabla e intentar eliminarla nuevamente.

ALTER TABLE `area` RENAME TO `area2`;
DROP TABLE IF EXISTS `area2`;

0

Encontré una solución fácil, exportar la base de datos, editar lo que desea editar en un editor de texto y luego importarlo. Hecho


4
Esa es una solución interesante, que probablemente no debería suceder. En su lugar, cualquier cosa que deba cambiarse debe hacerse a través del DBMS. La edición de un volcado de base de datos en un editor de texto parece una vía propicia para los problemas.
Brandon Anzaldi

1
Realmente no entiendo en qué estás metido. Volcar la base de datos, eliminar el CREATE TABLEcódigo y cargar el volcado nuevamente ... no hará que MySQL elimine la tabla. Y si te refieres a restaurar el volcado en una nueva base de datos ... Si quieres borrar todas las tablas como yo, una base de datos recién creada ya estará vacía. Si desea conservar algunas tablas, la SET FOREIGN_KEY_CHECKS=0solución alternativa mencionada en todas partes aquí funciona bien y es más simple; y probablemente no necesite editar el volcado de todos modos, ya que la nueva copia de sus datos posiblemente no tendrá un diccionario de datos desincronizado.
Álvaro González

-1

No se puede eliminar o actualizar una fila principal: falla una restricción de clave externa ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY ( user_id) REFERENCES user( id))

Lo que hice en dos sencillos pasos. primero elimino la fila secundaria en la tabla secundaria como

mysql> eliminar de la tabla2 donde role_id = 2 && user_id = 20;

Consulta correcta, 1 fila afectada (0,10 segundos)

y segundo paso como eliminar el padre

eliminar de la tabla1 donde id = 20;

Consulta correcta, 1 fila afectada (0,12 segundos)

Con esto resuelvo el problema que significa eliminar hijo y luego eliminar padre

Espero que lo tengas. :)


Por favor, lea la pregunta nuevamente. No puede eliminar una tabla que no existe.
Álvaro González

en este escenario, podemos eliminar la restricción de clave externa y luego intentar eliminar la tabla. podemos eliminar una clave externa como esta ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Aadil Masavir
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.