mysql 临时关闭约束_关于sql:如何暂时禁用MySQL中的外键约束?

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

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

要么我没有得到你想做的,要么你想要做的是非常,非常,非常丑陋。即使你能做到,你也许不应该这样做。

删除并重新应用FK正在改变您的数据库。你试图挑战允许系统看到某种意义的限制因素,它并不认为FK可能是一个暂时的东西,如果它确实知道,那就会引起恐慌。

你想做什么很奇怪。但是你使用的是哪个数据库?

@andrefsp:我正在使用MySQL。我将编辑我的问题以添加它。

如果您将其永久修改为ON DELETE SET NULL而不是禁用约束,该怎么办?这将完成类似的事情,你不必打开和关闭键检查。

@dnagirl:确实会更好。我怎样才能做到这一点?

你应该按照@dnagirl的要求去做。它的方式更合理,并且确保您不会以非常讨厌的方式处理数据。像你想做的那样玩它可能会导致严重的完整性和一致性问题。

试试DISABLE KEYS或

SET FOREIGN_KEY_CHECKS=0;

确保

SET FOREIGN_KEY_CHECKS=1;

后。

这是为mysql整体设置还是仅为该会话设置的东西?

我相信这是每次会议。

stackoverflow.com/questions/8538636/…

serverfault.com/questions/291100/… ,另请注意,Innodb不能disable keys

我可以为单个表禁用FOREIGN_KEY_CHECKS吗?

@Pacerier从阅读中看,它似乎可以,但仅适用于单个会话。

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

SET GLOBAL FOREIGN_KEY_CHECKS=0;

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

SET GLOBAL FOREIGN_KEY_CHECKS=1;

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

这是我需要知道的,所以这不是很好的练习,但这个家伙的回答应该是得分更高......

在尝试"最佳答案"后,这对我有用。也许可以添加对差异的解释。

@hexnet区别在于只有SET FOREIGN_KEY_CHECKS才会更改当前连接的值,而SET GLOBAL ..会更改所有连接的值,包括将来的连接。如果你只是在一个窗口中执行SET FOREIGN..,那么尝试在不同的窗口(通过不同的连接)中应用该语句,那里的值没有改变。对于GLOBAL,两个连接的相同变量具有相同的值。

回放更大的转储(6+ GB)<3时,唯一可以帮助我的东西

这对我不起作用。当我尝试时,我看到:ERROR 1228 (HY000): Variable 'foreign_key_checks' is a SESSION variable and can't be used with SET GLOBAL

尝试UPPERCASE @MikeB

@berniey没有运气。不过没关系。我使用alter语句暂时禁用外键约束。

@MikeB,我认为它与您用来发出命令的工具有关(它与myqsl命令行工具一起使用)。我一直在v5.5和5.6上使用该命令,它工作正常。文档建议甚至适用于v5.7。 dev.mysql.com/doc/refman/5.7/en/server-system-variables.html。此外,案件无关紧要(请原谅我之前的建议)

请注意,如果连接到在发出全局查询之前启用了外键检查的MySQL,则会保留外键检查的当前会话状态。即SET GLOBAL FOREIGN_KEY_CHECKS=0; SELECT @@FOREIGN_KEY_CHECKS;将返回1,直到您重新连接以开始新会话

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

SET FOREIGN_KEY_CHECKS=0;

TRUNCATE TABLE table;

SET FOREIGN_KEY_CHECKS=1;

不是禁用约束,而是永久地将其修改为ON DELETE SET NULL。这将完成类似的事情,你不必打开和关闭键检查。像这样:

请阅读此内容(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旁边会出现一个复选框,名为"启用外键检查"。

取消选中此复选框并运行SQL。它将在执行后自动重新检查。

谢谢!确实,解决方案SET FOREIGN_KEY_CHECKS=0; ..... SET FOREIGN_KEY_CHECKS=1;在PHPMyAdmin中对我不起作用,因为我忘了取消选中"启用外键检查"复选框。在PHPMyAdmin中,您可以跳过这些SET命令,只需取消选中该复选框即可。

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

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

仅供参考,mySQL 5.7抛出警告,运行DISABLE KEYS命令时InnoDB引擎没有此选项。

这确实有效,没有改变表它也不适合我

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

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

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

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

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

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

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

没错,总会有一个权衡。

没人说要永远这样运行它。您关闭约束,批量加载某些数据,然后重新打开它。没什么大不了的,人们总是这样做。

对于批量进口是必要的,至少对于性能来说,它是非常普遍的。有时您只需要恢复数据,然后您可以进行检查。

这不是问题的答案。

请注意,他的问题是暂时如何做到这一点。执行某些维护和数据导入时需要这样做。需要注意的是,导入脚本会对数据完整性负责。然后,稍后当重新打开索引和约束时,db将告诉您某些内容是否已损坏。

你有没有用过phpMyAdmin?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值