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 成功而应该成功,我阅读了以下网页...

'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?

...但他们似乎都没有解释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=1INSERT终于失败了……

ERROR 1452 (23000):无法添加或更新子行:外键 约束失败(sampdb.score, CONSTRAINT fk_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=0SET FOREIGN_KEY_CHECKS=0(后者的重复)之后,我能够重现该问题。这些一定是我发布问题时的设置,当我不知道@@GLOBAL@@SESSION。您之前的评论告诉我INSERT 成功的原因是@@SESSION.foreign_key_checks0。所以,即使@@GLOBAL.foreign_key_checks1@@SESSION.foreign_key_checks 也需要是1。谢谢。

以上是关于MySQL FORIEGN_KEY_CHECKS=1 默认情况下,但不工作的主要内容,如果未能解决你的问题,请参考以下文章

mysql初学,mysql修改,mysql查找,mysql删除,mysql基本命令

mysql(设置/更改mysql密码,连接MySQL,MySQL常用命令,MySQL两种引擎区别)

MySQL教程

MySQL

MySQL

有什么学习MySQL的好教程吗?