У меня есть таблица, в которой я храню все сообщения форума, опубликованные пользователями на моем сайте. Структура иерархии сообщений реализована с использованием модели Nested set .
Ниже приведена упрощенная структура таблицы:
- Id (ПЕРВИЧНЫЙ КЛЮЧ)
- Owner_Id (ИНОСТРАННЫЕ КЛЮЧЕВЫЕ ССЫЛКИ НА Id )
- Parent_Id (ИНОСТРАННЫЕ КЛЮЧЕВЫЕ ССЫЛКИ НА Id )
- Nleft
- NRight
- Nlevel
Теперь таблица выглядит примерно так:
+ ------- + ------------- + -------------- + ---------- + ----------- + ----------- +
| Id | Owner_Id | Parent_Id | nleft | nright | nlevel |
+ ------- + ------------- + -------------- + ---------- + ----------- + ----------- +
| 1 | 1 | NULL | 1 | 8 | 1 |
| 2 | 1 | 1 | 2 | 5 | 2 |
| 3 | 1 | 2 | 3 | 4 | 3 |
| 4 | 1 | 1 | 6 | 7 | 2 |
+ ------- + ------------- + -------------- + ---------- + ----------- + ----------- +
Обратите внимание, что первая строка является корневым сообщением, и дерево этого сообщения может быть отображено как:
-- SELECT * FROM forumTbl WHERE Owner_Id = 1 ORDER BY nleft;
MESSAGE (Id = 1)
MESSAGE (Id = 2)
Message (Id = 3)
Message (Id = 4)
Моя проблема возникает, когда я пытаюсь удалить все строки под одним и тем же Owner_Id
в одном запросе. Пример:
DELETE FROM forumTbl WHERE Owner_Id = 1 ORDER BY nright;
Вышеприведенный запрос завершается с ошибкой:
Код ошибки: 1451. Невозможно удалить или обновить родительскую строку: сбой ограничения внешнего ключа (
forumTbl
, CONSTRAINTOwner_Id_frgn
FOREIGN KEY (Owner_Id
) REFERENCESforumTbl
(Id
) ON DELETE NO ACTION ON UPDATE NO ACTION)
Причина в том, что первая строка , которая является корневым узлом ( Id=1
), также имеет то же значение в своем Owner_Id
поле ( Owner_Id=1
), и это вызывает сбой запроса из-за ограничения внешнего ключа.
Мой вопрос: как я могу предотвратить эту цикличность ограничения внешнего ключа и удалить строку, которая ссылается на себя? Есть ли способ сделать это без предварительного обновления Owner_Id
корневого ряда до NULL
?
Я создал демо этого сценария: http://sqlfiddle.com/#!9/fd1b1
Спасибо.
источник