748

是否可以暂时禁用 MySQL 中的约束?

我有两个 Django 模型,每个模型都有一个指向另一个模型的外键。由于外键约束,删除模型实例会返回错误:

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()  #a foreign key constraint fails here

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()

是否可以暂时禁用约束并删除?

4

10 回答 10

1625

尝试DISABLE KEYS

SET FOREIGN_KEY_CHECKS=0;

确保

SET FOREIGN_KEY_CHECKS=1;

后。

于 2013-03-19T14:07:45.653 回答
169

要全局关闭外键约束,请执行以下操作:

SET GLOBAL FOREIGN_KEY_CHECKS=0;

完成后记得把它放回去

SET GLOBAL FOREIGN_KEY_CHECKS=1;

警告:只有在进行单用户模式维护时才应该这样做。因为它可能导致数据不一致。例如,当您使用 mysqldump 输出上传大量数据时,它将非常有用。

于 2014-07-07T02:05:19.477 回答
66

我通常只在我想截断表时禁用外键约束,并且由于我不断回到这个答案,这是为了将来的我:

SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE table;
SET FOREIGN_KEY_CHECKS=1;
于 2015-03-25T16:48:42.223 回答
28

与其禁用约束,不如将其永久修改为 ON DELETE SET NULL。这将完成类似的事情,您不必打开和关闭密钥检查。像这样:

ALTER TABLE tablename1 DROP FOREIGN KEY fk_name1; //get rid of current constraints
ALTER TABLE tablename2 DROP FOREIGN KEY fk_name2;

ALTER TABLE tablename1 
  ADD FOREIGN KEY (table2_id) 
        REFERENCES table2(id)
        ON DELETE SET NULL  //add back constraint

ALTER TABLE tablename2 
  ADD FOREIGN KEY (table1_id) 
        REFERENCES table1(id)
        ON DELETE SET NULL //add back other constraint

阅读这个(http://dev.mysql.com/doc/refman/5.5/en/alter-table.html)和这个(http://dev.mysql.com/doc/refman/5.5/en /create-table-foreign-keys.html)。

于 2013-03-19T14:33:29.117 回答
23

全局关闭外键约束:

SET GLOBAL FOREIGN_KEY_CHECKS = 0;

对于活动外键约束:

SET GLOBAL FOREIGN_KEY_CHECKS = 1;
于 2018-01-11T09:49:24.543 回答
10

使用phpMyAdmin的一个非常简单的解决方案:

  • 在您的表格中,转到SQL选项卡
  • 编辑要运行的 SQL 命令后,旁边有一个GO名为“启用外键检查”的复选框。
  • 取消选中此复选框并运行您的 SQL。执行后会自动复查。
于 2017-04-19T04:26:09.267 回答
9

对我来说SET FOREIGN_KEY_CHECKS=0;还不够。我还在吃com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException

我不得不添加ALTER TABLE myTable DISABLE KEYS;.

所以:

SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE myTable DISABLE KEYS;
DELETE FROM myTable;
ALTER TABLE myTable ENABLE KEYS;
SET FOREIGN_KEY_CHECKS=1;
于 2018-10-12T10:16:36.407 回答
3

如果键字段可以为空,那么您还可以在尝试删除它之前将值设置为空:

cursor.execute("UPDATE myapp_item SET myapp_style_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed() 

cursor.execute("UPDATE myapp_style SET myapp_item_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()
于 2014-04-30T21:18:22.603 回答
3

phpMyAdmin中,您可以选择多行,然后单击删除操作。您将进入一个列出删除查询的屏幕。它看起来像这样:

在此处输入图像描述

请取消选中“启用外键检查”复选框,然后单击Yes以执行它们。

即使存在 ON DELETE 限制约束,这也将使您能够删除行。

于 2015-12-31T10:57:47.703 回答
-2

将外键约束设置为 0 不是一个好主意,因为如果这样做,您的数据库将无法确保它不违反参照完整性。这可能导致数据不准确、误导或不完整。

您创建外键是有原因的:因为子列中的所有值都应与父列中的值相同。如果没有外键约束,子行的值可能不在父行中,这会导致数据不准确。

例如,假设您有一个供学生登录的网站,并且每个学生都必须以用户身份注册一个帐户。您有一个用户 ID 表,用户 ID 作为主键;和另一个学生帐户表,以学生 ID 作为列。由于每个学生都必须有一个用户 ID,因此将学生帐户表中的学生 ID 设为引用用户 ID 表中主键用户 ID 的外键是有意义的。如果没有外键检查,一个学生最终可能有一个学生 ID 和没有用户 ID,这意味着一个学生可以在没有成为用户的情况下获得一个帐户,这是错误的。

想象一下,如果它发生在大量数据上。这就是您需要外键检查的原因。

最好找出导致错误的原因。最有可能的是,您尝试从父行中删除而不从子行中删除。在从父行删除之前尝试从子行中删除。

于 2015-01-14T10:21:37.303 回答