【问题标题】:Bogus foreign key constraint fail虚假外键约束失败
【发布时间】:2011-03-21 01:29:25
【问题描述】:

我收到此错误消息:

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

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

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),即表引用上没有架构名称:-?

标签: mysql innodb


【解决方案1】:

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

当使用 MySQL 查询浏览器或 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 的警告,但这个解决方案确实对我有用,在我确信我也删除了所有指向表的表的情况下麻烦的外键约束。
【解决方案2】:

两种可能:

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

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

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

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

【讨论】:

  • 我无法再重现该问题。字典不同步是一个可能的原因。我会测试一天,看看SHOW ENGINE INNODB STATUS 报告了什么。
  • 感谢您的回答!我有一个多对多表仍然引用我们无法删除的表,所以我必须先删除该表。
  • SHOW ENGINE INNODB STATUS 列出了“最新外键错误”下的最后一个外键错误。这有一个时间戳。
  • 可能有一个表仍然具有主题表的引用键。就我而言,就像这样。
  • 节省了很多时间。删除了“最新外键错误”下的数据库
【解决方案3】:

禁用外键检查

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。
【解决方案4】:

来自this blog

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

SET FOREIGN_KEY_CHECKS=0;

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

SET FOREIGN_KEY_CHECKS=1;

【讨论】:

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

希望它的工作

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

【讨论】:

  • 是的,它有效,就像之前提到过的几次一样;-)
【解决方案6】:

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

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

【讨论】:

    【解决方案7】:

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

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

    【讨论】:

      【解决方案8】:

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

      【讨论】:

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

      无法删除或更新父行:外键约束失败(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
      猜你喜欢
      • 2013-05-29
      • 1970-01-01
      • 2013-03-04
      • 2016-08-17
      • 2011-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      相关资源
      最近更新 更多