Как реализовать каскадное удаление иерархических данных в MySQL? - PullRequest
1 голос
/ 11 сентября 2009

Я работаю над проектом, в котором есть категории / подкатегории. Таблица базы данных для этого уникальна и имеет следующую структуру:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(11) NOT NULL auto_increment,
  `publish` tinyint(1) NOT NULL default '0',
  `parent_id` int(11) NOT NULL default '0',
  `description` text NOT NULL,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Таким образом, в случае, если категория является «базовой», parent_id равен нулю, а если у категории есть родительский элемент, он содержит идентификатор родительского элемента. Что я хочу знать, так это: мне нужно удалить все выше и связанные с категорией при выборе этой опции, каскадное удаление, но у меня есть только эта таблица (без внешних ключей) Как я могу это сделать? (Без большого количества запросов.)

Ответы [ 2 ]

4 голосов
/ 11 сентября 2009
  • Вы можете написать триггер для этого.

    DELIMITER //
    CREATE TRIGGER CatDelete AFTER DELETE ON categories
    FOR EACH ROW BEGIN
      DELETE FROM categories WHERE parent_id = old.id;
    END//
    DELIMITER ;
    
  • Вы можете ALTER своих таблиц MyISAM преобразовать в InnoDB, а затем определить ограничения внешнего ключа с помощью опции ON DELETE CASCADE.

    ALTER TABLE categories ENGINE=InnoDB;
    ALTER TABLE categories ADD CONSTRAINT 
      FOREIGN KEY (parent_id) REFERENCES categories (id) ON DELETE CASCADE;
    

Что касается вашего комментария, первое, что я проверю, это если у вас есть какие-то категории-сироты, то есть parent_id, указывающий на несуществующую строку. Это помешает вам создать ограничение.

SELECT c1.*
FROM categories c1
LEFT OUTER JOIN categories c2
  ON (c1.parent_id = c2.id)
WHERE c2.id IS NULL;
1 голос
/ 12 сентября 2009

Только мои 0,02 доллара - это не очень тривиальное решение, требующее MVC для обработки каскадного удаления.

...