MySQL FORIEGN_KEY_CHECKS=1 默认情况下,但不工作
Posted
技术标签:
【中文标题】MySQL FORIEGN_KEY_CHECKS=1 默认情况下,但不工作【英文标题】:MySQL FORIEGN_KEY_CHECKS=1 by default, but not working 【发布时间】:2019-06-18 21:53:48 【问题描述】:在 mysql Ver 14.14 Distrib 5.7.25 上,对于 Linux (x86_64),默认设置 @@GLOBAL.foreign_key_checks=1
似乎不起作用,因为我尝试将 INSERT
包含在父级中不存在的值的行表的键和INSERT
成功。
为什么我必须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)
所以,为了弄清楚为什么 INSERT
成功而应该不成功,我阅读了以下网页...
...但他们似乎都没有解释INSERT
为何/如何成功(不幸的是)。
我确保我的 3 张桌子满足以下所有条件:
外键必须是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):无法添加或更新子行:外键 约束失败(
sampdb
.score
, CONSTRAINTfk_event_id
FOREIGN 关键 (event_id
) 参考grace_event
(event_id
) 更新 级联)
为什么我必须SET FOREIGN_KEY_CHECKS=1
(显然)已经默认设置为 1? 默认@@GLOBAL.foreign_key_checks
设置没有任何意义吗?这是一个错误吗?
【问题讨论】:
什么返回SELECT @@GLOBAL.foreign_key_checks, @@SESSION.foreign_key_checks;
?.
@wchiquito 每个都返回1
。
@wchiquito 我猜这意味着在我运行SET FOREIGN_KEY_CHECKS=1
之前必须将@@SESSION.foreign_key_checks
设置为0
。对吗?
【参考方案1】:
我无法重现该问题:
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.25 |
+-----------+
1 row in set (0.00 sec)
mysql> SELECT @@GLOBAL.foreign_key_checks, @@SESSION.foreign_key_checks;
+-----------------------------+------------------------------+
| @@GLOBAL.foreign_key_checks | @@SESSION.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)
【讨论】:
在执行SET @@GLOBAL.foreign_key_checks=1;
、SET @@SESSION.foreign_key_checks=0
和SET FOREIGN_KEY_CHECKS=0
(后者的重复)之后,我能够重现该问题。这些一定是我发布问题时的设置,当我不知道@@GLOBAL
和@@SESSION
。您之前的评论告诉我INSERT
成功的原因是@@SESSION.foreign_key_checks
是0
。所以,即使@@GLOBAL.foreign_key_checks
是1
,@@SESSION.foreign_key_checks
也需要是1
。谢谢。以上是关于MySQL FORIEGN_KEY_CHECKS=1 默认情况下,但不工作的主要内容,如果未能解决你的问题,请参考以下文章
mysql初学,mysql修改,mysql查找,mysql删除,mysql基本命令