如何临时禁用MySQL中的外键约束?

时间:2013-03-19 14:03:59

标签: mysql sql django

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

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

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()

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

10 个答案:

答案 0 :(得分:1305)

尝试DISABLE KEYS

SET FOREIGN_KEY_CHECKS=0;

确保

SET FOREIGN_KEY_CHECKS=1;

后。

答案 1 :(得分:123)

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

SET GLOBAL FOREIGN_KEY_CHECKS=0;

并记得在完成后将其重新设置

SET GLOBAL FOREIGN_KEY_CHECKS=1;

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

答案 2 :(得分:44)

我通常只在要截断表时才禁用外键约束,因为我不断回到这个答案,这是为了将来的我:

SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE table;
SET FOREIGN_KEY_CHECKS=1;

答案 3 :(得分:25)

不是禁用约束,而是将其永久修改为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)。

答案 4 :(得分:10)

全局关闭外键约束:

SET GLOBAL FOREIGN_KEY_CHECKS = 0;

和活动外键约束

SET GLOBAL FOREIGN_KEY_CHECKS = 1;

答案 5 :(得分:8)

phpmyadmin的一个非常简单的解决方案:

  • 在表格中,转到 SQL 标签
  • 编辑要运行的SQL命令后, GO 旁边会出现一个复选框,名为“启用外键检查”
  • 取消选中此复选框并运行SQL 。它将在执行后自动重新检查。

答案 6 :(得分:3)

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

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()

答案 7 :(得分:1)

对我来说,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;

答案 8 :(得分:0)

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

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

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

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

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

答案 9 :(得分:0)

在phpMyAdmin中,您可以选择多行,然后单击删除操作。您将进入一个列出删除查询的屏幕,您可以取消选中外键检查,然后单击是以执行它们。

即使存在ON DELETE限制约束,也可以删除行。