ChatGPT解决这个技术问题 Extra ChatGPT

虚假外键约束失败

我收到此错误消息:

第 40 行的错误 1217 (23000):无法删除或更新父行:外键约束失败

...当我尝试删除表格时:

DROP TABLE IF EXISTS `area`;

...定义如下:

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;

有趣的是,我已经删除了架构中具有针对 area 的外键的所有其他表。实际上,除了 area 表之外,数据库是空的。

如果数据库中没有任何其他对象,它怎么可能有子行?据我所知,InnoDB 不允许在其他模式上使用外键,是吗?

(我什至可以运行 RENAME TABLE area TO something_else 命令 :-?)

该表是否可能是另一个模式中的参照完整性关系的一部分?
我有一些其他的应用程序副本,所以总是有可能的。但是,我使用的语法基本上是 CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id),即表引用上没有模式名称:-?

K
Karlis Rode

按需,现在作为答案...

使用 MySQL Query Browser 或 phpMyAdmin 时,似乎为每个查询打开了一个新连接 (bugs.mysql.com/bug.php?id=8280),因此有必要在一个查询中编写所有 drop 语句,例如。

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

SET FOREIGN_KEY_CHECKS=1 用作额外安全措施的地方...


对于那些使用 phpMyAdmin 创建转储的人,有一个选项“禁用外键检查”会自动将 SET FOREIGN_KEY_CHECKS=0; 添加到转储的开头。
好像 phpMyAdmin 已经实现了这个可爱的功能,现在我正在等待 mysqlWorkbench 做同样的事情! :)
@CodeMed 仅供参考,我接受了 MarkR 的回答,因为它为这个问题提供了一个有意义的解释——尽管我承认我无法验证它,因为我在接下来的 6 年中没有遇到过同样的问题,甚至一次都没有。这个和之前的答案提供了一种解决方法(很好),但并没有真正解决问题本身,因为你只能接受我必须选择的一个答案。
警告: 这不是解决方案,而是懒人的解决方法。使用此方法后(其他一些表上的记录指向已删除的表),您将遇到悬空外键,这会严重破坏数据库的一致性(ACID 中的 C),并且您的应用程序将开始到处抛出异常。你已经被警告过了。
虽然我确信应该理解和注意 bekce 的警告,但这个解决方案确实对我有用,在这种情况下,我确信我也会删除所有指向具有麻烦的外键约束的表的表。
M
MarkR

两种可能:

在另一个模式(mysql 术语中的“数据库”)中有一个表,它有一个 FK 引用 innodb 内部数据字典与 mysql 不同步。

您可以通过在删除失败后执行“SHOW ENGINE INNODB STATUS”来查看它是哪个表(无论如何是其中一个)。

如果结果是后一种情况,如果可以的话,我会转储并恢复整个服务器。

MySQL 5.1 及更高版本将在错误消息中为您提供带有 FK 的表的名称。


我无法再重现该问题。字典不同步是一个可能的原因。我会在一天内对其进行测试,看看 SHOW ENGINE INNODB STATUS 报告了什么。
谢谢你的回答!我有一个多对多表仍然引用我们无法删除的表,所以我必须先删除该表。
SHOW ENGINE INNODB STATUS 在“LATEST FOREIGN KEY ERROR”下列出了最后一个外键错误。这有一个时间戳。
可能有一个表仍然具有主题表的引用键。就我而言,就像这样。
节省了很多时间。删除了“最新外键错误”下的数据库
Á
Álvaro González

禁用外键检查

SET FOREIGN_KEY_CHECKS=0

正确的命令似乎是 SET FOREIGN_KEY_CHECKS=0,它确实修复了错误消息。您知道为什么需要这样做吗?即使在表消失后,外键是否也会被缓存?
说实话,我不知道为什么会出现这样的问题,但请确保在每次进行重大更改或更新时禁用密钥检查。这件事发生在我身上好几次,让我好几天没睡。
完成后请务必SET FOREIGN_KEY_CHECKS=1;
使用 MySQL Query Browser 或 phpMyAdmin 时,似乎为每个查询打开了一个新连接 (bugs.mysql.com/bug.php?id=8280),因此有必要在一个查询中编写所有 drop 语句,例如。 SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS=1 用作额外的安全措施...
@KarlisRode,Bravo 对 phpMyAdmin 的评论。如果您将其作为答案,我会+1。
J
JackD

来自 this blog

您可以暂时禁用外键检查:

SET FOREIGN_KEY_CHECKS=0;

一旦你搞砸了,一定要恢复它们:

SET FOREIGN_KEY_CHECKS=1;

很好的答案,因为我在本地开发:)
这是一个有效的解决方法(我可以确认它有效),但链接的博客条目并没有真正谈论这个问题中的场景(一个已经为空的数据库保存一个表)。
M
M_ Fa

希望它的工作

SET foreign_key_checks = 0;删除表 table name; SET foreign_key_checks = 1;


是的,它有效,就像之前提到过的几次一样;-)
y
yeyo

在 Rails 上,可以使用 rails console 执行以下操作:

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

V
Vadim Pluzhinsky

也许您以前在使用此表时收到错误。您可以重命名该表并再次尝试将其删除。

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

A
Abdulrahman K

我找到了一个简单的解决方案,导出数据库,在文本编辑器中编辑您想要编辑的内容,然后导入它。完毕


这是一个有趣的解决方案,实际上可能不应该发生。相反,任何需要更改的东西都应该通过 DBMS 来完成。在文本编辑器中编辑数据库转储似乎是解决问题的成熟途径。
我真的不明白你在做什么。转储数据库、删除 CREATE TABLE 代码并再次加载转储...不会使 MySQL 删除表。如果你的意思是在一个新的数据库中恢复转储......如果你想像我一样清除所有的表,一个新创建的数据库已经是空的。如果您想保留一些表,此处提到的 SET FOREIGN_KEY_CHECKS=0 解决方法可以正常工作并且更简单;并且您可能无论如何都不需要编辑转储,因为您的数据的新副本可能没有不同步的数据字典。
A
Aadil Masavir

无法删除或更新父行:外键约束失败(table1.user_role、CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60 FOREIGN KEY (user_id) REFERENCES user (id))

我做了两个简单的步骤。首先我删除子表中的子行,例如

mysql> 从 table2 中删除其中 role_id = 2 && user_id =20;

查询正常,1 行受影响(0.10 秒)

第二步是删除父级

从 id = 20 的 table1 中删除;

查询正常,1 行受影响(0.12 秒)

通过这个我解决了问题,这意味着删除孩子然后删除父母

我希望你明白了。 :)


请再次阅读问题。您不能删除不存在的表。
在这种情况下,我们可以删除外键约束,然后尝试删除表。我们可以像这样删除外键 ALTER TABLE DROP CONSTRAINT