Можно ли использовать ограничения на иерархических данных в таблице самоопределения? - PullRequest
1 голос
/ 01 июня 2010

Предположим, у вас есть следующая таблица, предназначенная для представления иерархических данных:

+--------+-------------+
| Field  | Type        |
+--------+-------------+
| id     | int(10)     |
| parent | int(10)     |
| name   | varchar(45) |
+--------+-------------+

Таблица является самореферентной в том смысле, что parent_id относится к id.

Таким образом, у вас могут быть следующие данные:

+----+--------+---------------+
| id | parent | name          |
+----+--------+---------------+
|  1 |      0 | fruit         |
|  2 |      0 | vegetable     |
|  3 |      1 | apple         |
|  4 |      1 | orange        |
|  5 |      3 | red delicious |
|  6 |      3 | granny smith  |
|  7 |      3 | gala          |
+----+--------+---------------+

Используя MySQL , я пытаюсь наложить (внешне-ссылочные) ограничения внешнего ключа на данные для каскадного обновления и предотвратить удаление записи, если в ней есть «потомки».

Итак, я использовал следующее:

CREATE TABLE `test`.`fruit` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `parent` INT(10) UNSIGNED,
  `name` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `fk_parent`
    FOREIGN KEY (`parent`)
    REFERENCES `fruit` (`id`)
    ON UPDATE CASCADE
    ON DELETE RESTRICT
)
ENGINE = InnoDB;

Из того, что я понимаю, это должно соответствовать моим требованиям. (И parent должен по умолчанию иметь значение null, чтобы разрешить вставки, правильно?)

Проблема в том, что если я изменю id записи, она не будет каскадной:

Cannot delete or update a parent row: a foreign key constraint fails (`test`.`fruit`, CONSTRAINT `fk_parent` FOREIGN KEY (`parent`) REFERENCES `fruit` (`id`) ON UPDATE CASCADE)

Чего мне не хватает?

Не стесняйтесь поправлять меня, если моя терминология испорчена ... Я новичок в ограничениях.

1 Ответ

2 голосов
/ 02 июня 2010

Отклонение от стандартов SQL: если ON UPDATE CASCADE или ON UPDATE SET NULL рекурсивно обновляет ту же таблицу, которую ранее обновляла во время каскада, это действует как ОГРАНИЧЕНИЕ. Это означает, что вы не можете использовать операции самообращения ON UPDATE CASCADE или ON UPDATE SET NULL. Это необходимо для предотвращения бесконечных циклов, возникающих в результате каскадных обновлений. С другой стороны, возможна ссылка на ON DELETE SET NULL, как и ссылка на ON DELETE CASCADE. Каскадные операции не могут быть вложены более чем на 15 уровней.

...