Как рекурсивно удалить элементы из таблицы? - PullRequest
3 голосов
/ 13 февраля 2012

У меня в MySQL таблица "папки":

CREATE TABLE IF NOT EXISTS `folders` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `folder_key` varchar(40) NOT NULL,
  `parent_key` varchar(40) NOT NULL,
  `name` varchar(16) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Я не использую целочисленные идентификаторы, только ключи (буквенно-цифровые хэши, которые я заменил словами, чтобы сделать вещи более понятными). Итак, folder_key & parent_key - это хэши SHA-1 (в моем реальном приложении).

INSERT INTO `folders` (`id`, `folder_key`, `parent_key`, `name`) VALUES
(1, 'sun', 'root', '1'),
(2, 'moon', 'sun', '1.1'),
(3, 'jupiter', 'moon', '1.1.1'),
(4, 'mars', 'root', '2');

Как видите, у первого элемента тоже есть parent_key, это корневой ключ.

Контрольный пример: Если я хочу удалить элемент с помощью folder_key === moon (1.1), он также должен удалить свои дочерние элементы, в этом случае это элемент с folder_key === jupiter (1.1 .1) и так далее ...

Допустим, я хочу удалить несколько элементов, поэтому я делаю:

DELETE from folders WHERE folder_key IN('moon', 'mars'); После выполнения в таблице должен быть только один элемент с folder_key === sun

Итак, вопрос в следующем: Как удалить элементы из этой таблицы, имеющие один или несколько ключей folder_keys (рекурсивно) с триггерами MySQL, ON DELETE CASCADE или ...?

Спасибо.

Ответы [ 4 ]

3 голосов
/ 13 февраля 2012

В этой модели это невозможно

  1. Вместо корня используйте NULL, поэтому вы можете использовать внешний ключ InnoDB + Каскадное удаление.
  2. Вместо использования строки parent_key используйте id (например, солнце = 1, луна = 2)

Другой способ - изменить модель данных, чтобы можно было легко выбрать любые потомки элемента - см., например, http://www.sitepoint.com/hierarchical-data-database-2/

3 голосов
/ 13 февраля 2012

Вы можете добавить ИНОСТРАННЫЙ КЛЮЧ на folders с опцией КАСКАД для УДАЛИТЬ:

ALTER TABLE `folders` ADD CONSTRAINT `FK_folder_parent` FOREIGN KEY `FK_folder_parent` (`parent_key`)
REFERENCES `folders` (`folder_key`)
ON DELETE CASCADE
ON UPDATE CASCADE

http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html

2 голосов
/ 13 февраля 2012

Вместо хранения значения "Родительский ключ" сохраните их идентификатор

CREATE TABLE IF NOT EXISTS `folders` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `folder_key` varchar(40) NOT NULL,
  `parent_key` int(11) NOT NULL,
  `name` varchar(16) NOT NULL,
  PRIMARY KEY (`id`)
foreign key(`parent_key`) on delete cascade
) ENGINE=InnoDB;
0 голосов
/ 16 августа 2012

@ Нэвин

вы должны использовать те же типы данных при создании ограничения каскадного удаления. Теперь у вас есть неподписанный int и подписанный int.

...