2016-09-22 4 views
2

Я довольно новичок в StackOverflow, поэтому, пожалуйста, извините, если я делаю что-то неправильно. И извините за мой английский - это не мой родной язык.Внешние ключи иногда работают в MySQL

Хорошо, сделайте длинный рассказ коротким. Я использую:

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 

стол 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 

Как вы можете видеть - впереди ign, связывающие эти таблицы с ON УДАЛИТЬ УСТАНОВКУ 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) 

Работа. Весело. Еще смешнее (sources_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) 

Так что мой вопрос очевиден. Что это было? И как заставить его работать во всех случаях, как ожидалось? Любая помощь высоко ценится. Заранее спасибо!

ответ

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 первой, прежде чем сделать это ограничение.

+0

Большое спасибо! Я начал думать, что я сумасшедший. Работает как шарм! Какая жалость ... –

+0

рад помочь – e4c5

Смежные вопросы