是否可以暂时禁用 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()
是否可以暂时禁用约束并删除?
ON DELETE SET NULL
,该怎么办?这将完成类似的事情,您不必打开和关闭密钥检查。
尝试 DISABLE KEYS
或
SET FOREIGN_KEY_CHECKS=0;
确保
SET FOREIGN_KEY_CHECKS=1;
后。
要全局关闭外键约束,请执行以下操作:
SET GLOBAL FOREIGN_KEY_CHECKS=0;
完成后记得把它放回去
SET GLOBAL FOREIGN_KEY_CHECKS=1;
警告:只有在进行单用户模式维护时才应该这样做。因为它可能导致数据不一致。例如,当您使用 mysqldump 输出上传大量数据时,它将非常有用。
SET FOREIGN_KEY_CHECKS
只是更改了 当前连接 的值,而 SET GLOBAL ..
更改了 所有连接 的值,包括未来的连接。如果您只是在一个窗口中执行 SET FOREIGN..
,然后尝试在不同的窗口(通过不同的连接)应用该语句,则该值没有改变。使用 GLOBAL
,相同的变量对于两个连接具有相同的值。
ERROR 1228 (HY000): Variable 'foreign_key_checks' is a SESSION variable and can't be used with SET GLOBAL
我通常只在我想截断表时禁用外键约束,并且由于我不断回到这个答案,这是为了将来的我:
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE table;
SET FOREIGN_KEY_CHECKS=1;
与其禁用约束,不如将其永久修改为 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)。
FOREIGN_KEY_CHECKS
为 0 并在脏工作完成后将其放回原处。此外,它可能会锁定以写入您的表格。
全局关闭外键约束:
SET GLOBAL FOREIGN_KEY_CHECKS = 0;
对于活动外键约束:
SET GLOBAL FOREIGN_KEY_CHECKS = 1;
phpMyAdmin 的一个非常简单的解决方案:
在您的表中,转到 SQL 选项卡
编辑要运行的 SQL 命令后,GO 旁边有一个复选框,名为 'Enable foreign key checks' 。
取消选中此复选框并运行您的 SQL。执行后会自动复查。
SET FOREIGN_KEY_CHECKS=0; ..... SET FOREIGN_KEY_CHECKS=1;
在 PHPMyAdmin 中对我不起作用,因为我忘记取消选中“启用外键检查”复选框。在 PHPMyAdmin 中,您可以跳过这些 SET 命令并取消选中该复选框。
对我来说,仅 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;
如果键字段可以为空,那么您还可以在尝试删除它之前将值设置为空:
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()
在 phpMyAdmin 中,您可以选择多行,然后单击删除操作。您将进入一个列出删除查询的屏幕。它看起来像这样:
https://i.stack.imgur.com/Y8Xgv.png
请取消选中“启用外键检查”复选框,然后单击“是”执行它们。
即使存在 ON DELETE 限制约束,这也将使您能够删除行。
将外键约束设置为 0 不是一个好主意,因为如果这样做,您的数据库将无法确保它不违反参照完整性。这可能导致数据不准确、误导或不完整。
您创建外键是有原因的:因为子列中的所有值都应与父列中的值相同。如果没有外键约束,子行的值可能不在父行中,这会导致数据不准确。
例如,假设您有一个供学生登录的网站,并且每个学生都必须以用户身份注册一个帐户。您有一个用户 ID 表,用户 ID 作为主键;和另一个学生帐户表,以学生 ID 作为列。由于每个学生都必须有一个用户 ID,因此将学生帐户表中的学生 ID 设为引用用户 ID 表中主键用户 ID 的外键是有意义的。如果没有外键检查,一个学生最终可能有一个学生 ID 和没有用户 ID,这意味着一个学生可以在没有成为用户的情况下获得一个帐户,这是错误的。
想象一下,如果它发生在大量数据上。这就是您需要外键检查的原因。
最好找出导致错误的原因。最有可能的是,您尝试从父行中删除而不从子行中删除。在从父行删除之前尝试从子行中删除。
不定期副业成功案例分享
disable keys
为 InnodbDISABLE KEYS
。但是您可以使用显示的其他命令完成此问题中的要求:SET FOREIGN_KEY_CHECKS=0;
(起初我以为他说没有办法完成此操作。)