首页 文章

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

提问于
浏览
493

是否有可能暂时禁用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()

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

11 回答

  • 110

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

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

  • 0

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

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

    试试 DISABLE KEYS

    SET FOREIGN_KEY_CHECKS=0;
    

    确保

    SET FOREIGN_KEY_CHECKS=1;
    

    后 .

  • 0

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

    SET GLOBAL FOREIGN_KEY_CHECKS=0;
    

    并记得在完成后将其设置回来

    SET GLOBAL FOREIGN_KEY_CHECKS=1;
    

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

  • 3

    对我来说只是 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;
    
  • -3

    一个非常简单的解决方案,使用phpmyadmin:在你的表中,转到SQL选项卡,在编辑要运行的SQL命令后,在GO旁边有一个复选框'启用外键检查' . 禁用此复选框并运行SQL . 然后会自动重新检查 .

  • 1178

    而不是禁用您的约束,永久修改它为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) .

  • 0

    如果键字段可以为空,那么您也可以在尝试删除它之前将该值设置为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()
    
  • 5

    禁用:SET GLOBAL FOREIGN_KEY_CHECKS = 0;

    启用:SET GLOBAL FOREIGN_KEY_CHECKS = 1;

  • 41

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

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

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

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

    最好弄清楚导致错误的原因 . 您很可能尝试从父行删除而不从子行中删除 . 尝试从父行删除之前从父行删除 .

  • 7

    要全局关闭外键约束:

    SET GLOBAL FOREIGN_KEY_CHECKS = 0;
    

    并用于活动外键约束

    SET GLOBAL FOREIGN_KEY_CHECKS = 1;
    

相关问题