外键在MySQL中偶尔工作

时间:2016-09-22 11:21:07

标签: mysql foreign-keys

我是StackOverflow的新手,所以如果我做错了,请抱歉。抱歉我的英语 - 这不是我的母语。

好的,长话短说。我正在使用:

 Server version: 5.6.31 MySQL Community Server (GPL)

我有两张这样的表:

表格文字

CREATE TABLE `texts` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `body` text,
  `source_id` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `texts_sources_key` (`source_id`),
  CONSTRAINT `texts_sources_key` FOREIGN KEY (`source_id`) REFERENCES `texts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

table texts_sources

CREATE TABLE `texts_sources` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `short_desc` varchar(255) DEFAULT NULL,
  `long_desc` text,
  `url` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 

如您所见 - 有外键将这些表与 ON DELETE SET NULL ON UPDATE CASCADE 相关联。

这是初始数据:

mysql> select * from texts;
+----+------+-----------+
| id | body | source_id |
+----+------+-----------+
|  1 | ***  |         1 |
+----+------+-----------+
1 row in set (0.00 sec)

mysql> select * from texts_sources;
+----+------------+-----------+----------------+
| id | short_desc | long_desc | url            |
+----+------------+-----------+----------------+
|  1 | *          | NULL      | http://url.com |
+----+------------+-----------+----------------+
1 row in set (0.00 sec)

现在让我们做一些魔术。

mysql> update texts_sources set id=5;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from texts_sources;
+----+------------+-----------+----------------+
| id | short_desc | long_desc | url            |
+----+------------+-----------+----------------+
|  5 | *          | NULL      | http://url.com |
+----+------------+-----------+----------------+
1 row in set (0.01 sec)

mysql> select * from texts;
+----+------+-----------+
| id | body | source_id |
+----+------+-----------+
|  1 | ***  |         1 |
+----+------+-----------+
1 row in set (0.00 sec)

不工作。更有趣:

mysql> delete from texts_sources;
Query OK, 1 row affected (0.18 sec)

mysql> select * from texts;
+----+------+-----------+
| id | body | source_id |
+----+------+-----------+
|  1 | ***  |         1 |
+----+------+-----------+
1 row in set (0.00 sec)

不工作。好。也许它根本不起作用。让我们试试这个:

mysql> update texts set source_id=5;
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`serj_by`.`texts`, CONSTRAINT `humor_sources_key` FOREIGN KEY (`source_id`) REFERENCES `texts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE)
mysql> insert into texts (body, source_id) values ("***", 7);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`serj_by`.`texts`, CONSTRAINT `humor_sources_key` FOREIGN KEY (`source_id`) REFERENCES `texts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE)

工作。乐趣。甚至更有趣(texts_sources是空的,希望你记得):

mysql> insert into texts (body, source_id) values ("***", 1);
Query OK, 1 row affected (0.16 sec)

mysql> select * from texts_sources;
Empty set (0.00 sec)

mysql> select * from texts;
+----+------+-----------+
| id | body | source_id |
+----+------+-----------+
|  1 | ***  |         1 |
|  2 | ***  |         1 |
+----+------+-----------+
2 rows in set (0.00 sec)

所以我的问题很明显。这是啥?如何使其在所有情况下都按预期工作?任何帮助都非常感谢。提前谢谢!

1 个答案:

答案 0 :(得分:2)

让我们仔细看看:

CONSTRAINT `texts_sources_key` 
  FOREIGN KEY (`source_id`) 
    REFERENCES `texts` (`id`) ON DELETE SET NULL ON UPDATE CASCADE

虽然您将此命名为texts_sources_key,但外键实际上引用了同一个表中的列。你可能想要它

CONSTRAINT `texts_sources_key` 
  FOREIGN KEY (`source_id`) 
    REFERENCES `texts_sources` (`id`) ON DELETE SET NULL ON UPDATE CASCADE

另外,在创建约束之前,您需要先创建text_sources表。