MySQL默认情况下FORIEGN_KEY_CHECKS=1,但无效。
MySQL默认情况下FORIEGN_KEY_CHECKS=1,但无效。
在MySQL Ver 14.14 Distrib 5.7.25上,对于Linux(x86_64)来说,默认设置@@GLOBAL.foreign_key_checks=1
似乎不起作用,因为我尝试插入一行包含父表键中不存在的值的数据,插入操作竟然成功了。
为什么我必须执行SET FOREIGN_KEY_CHECKS=1
,即使默认情况下已经设置了foreign_key_checks=1
?
例如,我有一个表如下:
mysql> SHOW CREATE TABLE score\G *************************** 1. row *************************** Table: score Create Table: CREATE TABLE `score` ( `student_id` int(10) unsigned NOT NULL, `event_id` int(10) unsigned NOT NULL, `score` int(11) NOT NULL, PRIMARY KEY (`event_id`,`student_id`), KEY `student_id` (`student_id`), CONSTRAINT `fk_event_id` FOREIGN KEY (`event_id`) REFERENCES `grace_event` (`event_id`) ON UPDATE CASCADE, CONSTRAINT `fk_student_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`student_id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 1 row in set (0.00 sec)
...我输入mysql> INSERT INTO score (event_id,student_id,score) VALUES(9999,9999,0);
然后得到了如下结果...
Query OK, 1 row affected (0.01 sec)
所以,为了弄清楚为什么这个插入操作在不应该成功的情况下却成功了,我阅读了以下网页...
- 'SET foreign_key_checks = 1' does not work again
- Foreign key not working in MySQL: Why can I INSERT a value that's not in the foreign column?
...但是其中没有一个解释了为什么这个插入操作成功了(不幸的是)。
我确保我三个表的以下条件都满足:
- 外键必须是
INT UNSIGNED
。是的。 - 默认存储引擎必须是
InnoDB
。是的。 - 对于每个外键声明,使用
ON UPDATE CASCADE
。是的。 - phpmyadmin显示
foreign key checks
设置为ON
。是的。
...并且SELECT @@GLOBAL.foreign_key_checks
显示...
mysql> SELECT @@GLOBAL.foreign_key_checks; +-----------------------------+ | @@GLOBAL.foreign_key_checks | +-----------------------------+ | 1 | +-----------------------------+
在上述所有设置的情况下,mysql> INSERT INTO score (event_id,student_id,score) VALUES(9999,9999,0);
仍然成功了。
直到我执行了SET FOREIGN_KEY_CHECKS=1
,INSERT
才最终失败了...
ERROR 1452 (23000): Cannot add or update a child row: a foreign key
constraint fails (
sampdb
.score
, CONSTRAINTfk_event_id
FOREIGNKEY (
event_id
) REFERENCESgrace_event
(event_id
) ON UPDATECASCADE)
为什么我在默认情况下(显然)已经设置为1的情况下,仍然需要执行SET FOREIGN_KEY_CHECKS=1
?默认的@@GLOBAL.foreign_key_checks
设置没有起作用吗?这是一个bug吗?
问题出现的原因是在执行插入操作时,外键约束检查失败。解决方法是将foreign_key_checks设置为1。
文章内容如下:
MySQL默认情况下,foreign_key_checks的值为1,但是在某些情况下可能会出现无法正常工作的情况。下面是一个例子:
mysql> SELECT VERSION(); +-----------+ | VERSION() | +-----------+ | 5.7.25 | +-----------+ 1 row in set (0.00 sec) mysql> SELECT @.foreign_key_checks, @.foreign_key_checks; +-----------------------------+------------------------------+ | @.foreign_key_checks | @.foreign_key_checks | +-----------------------------+------------------------------+ | 1 | 1 | +-----------------------------+------------------------------+ 1 row in set (0.00 sec) mysql> DROP TABLE IF EXISTS `student`, `grace_event`, `score`; Query OK, 0 rows affected, 3 warnings (0.00 sec) mysql> CREATE TABLE IF NOT EXISTS `student` ( -> `student_id` int(10) unsigned NOT NULL PRIMARY KEY -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE IF NOT EXISTS `grace_event` ( -> `grace_event` int(10) unsigned NOT NULL PRIMARY KEY -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE IF NOT EXISTS `score` ( -> `student_id` int(10) unsigned NOT NULL, -> `event_id` int(10) unsigned NOT NULL, -> `score` int(11) NOT NULL, -> PRIMARY KEY (`event_id`,`student_id`), -> KEY `student_id` (`student_id`), -> CONSTRAINT `fk_event_id` FOREIGN KEY (`event_id`) -> REFERENCES `grace_event` (`grace_event`) ON UPDATE CASCADE, -> CONSTRAINT `fk_student_id` FOREIGN KEY (`student_id`) -> REFERENCES `student` (`student_id`) ON UPDATE CASCADE -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO `score` -> (`event_id`, `student_id`, `score`) -> VALUES -> (9999, 9999, 0); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`score`, CONSTRAINT `fk_event_id` FOREIGN KEY (`event_id`) REFERENCES `grace_event` (`grace_event`) ON UPDATE CASCADE)
在上述例子中,当我们执行插入操作时,出现了外键约束检查失败的错误。我们尝试了将foreign_key_checks设置为1,但是问题仍然存在。
经过一番探索,我们发现了解决方法。我们可以通过将foreign_key_checks设置为1来解决这个问题。
希望这篇文章对你有所帮助!