Операционные иерархические данные MySQL

У меня есть структура таблицы MySQL:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int(10) unsigned NOT NULL DEFAULT '0',
  `name` varchar(255) NOT NULL DEFAULT '',
  `is_working` tinyint(1) unsigned NOT NULL DEFAULT '1',
);

который содержит иерархические данные с отношениями id и parent_id

У меня есть дерево глубины 5 уровней, например:

CATEGORY LEVEL 1
  SUBCAT LEVEL 2
    SUBCAT LEVEL 3
      SUBCAT LEVEL 4
        SUBCAT LEVEL 5

Мне нужно (вопрос): если я устанавливаю is_working= 0 для какой-либо категории или подкатегории, is_working устанавливается на 0 для всех его подкатегорий.

Ответ 1

Я использую другой дизайн, и хотя он имеет ограничения, если вы можете их перенести, он очень прост и очень эффективен.

Вот пример таксономического дерева птиц, поэтому иерархия - это класс/порядок/семья/род/вид - вид - самый низкий уровень, 1 строка = 1 вид:

CREATE TABLE `taxons` (
  `TaxonId` smallint(6) NOT NULL default '0',
  `ClassId` smallint(6) default NULL,
  `OrderId` smallint(6) default NULL,
  `FamilyId` smallint(6) default NULL,
  `GenusId` smallint(6) default NULL,
  `Name` varchar(150) NOT NULL default ''
);

и пример данных:

+---------+---------+---------+----------+---------+-------------------------------+
| TaxonId | ClassId | OrderId | FamilyId | GenusId | Name                          |
+---------+---------+---------+----------+---------+-------------------------------+
|     254 |       0 |       0 |        0 |       0 | Aves                          |
|     255 |     254 |       0 |        0 |       0 | Gaviiformes                   |
|     256 |     254 |     255 |        0 |       0 | Gaviidae                      |
|     257 |     254 |     255 |      256 |       0 | Gavia                         |
|     258 |     254 |     255 |      256 |     257 | Gavia stellata                |
|     259 |     254 |     255 |      256 |     257 | Gavia arctica                 |
|     260 |     254 |     255 |      256 |     257 | Gavia immer                   |
|     261 |     254 |     255 |      256 |     257 | Gavia adamsii                 |
|     262 |     254 |       0 |        0 |       0 | Podicipediformes              |
|     263 |     254 |     262 |        0 |       0 | Podicipedidae                 |
|     264 |     254 |     262 |      263 |       0 | Tachybaptus                   |

Это здорово, потому что таким образом вы выполняете все необходимые операции очень простым способом, если категории не меняют свой уровень в дереве.

Ответ 2

Вы можете использовать триггеры для выполнения рекурсивного обновления.

посмотрите на это: http://dev.mysql.com/doc/refman/5.0/en/triggers.html

Это просто идея, я не пробую этот код.

delimiter //
CREATE TRIGGER categoriesUpdateTrg BEFORE UPDATE ON categories
    FOR EACH ROW BEGIN
    IF (NEW.is_working<>OLD.is_working) THEN
        UPDATE categories SET is_working=NEW.id_working WHERE parent_id=NEW.id;
        END IF;
    END;
//
delimiter ;

триггер выполняется при каждом обновлении по таблице "категории". Для каждой обновленной строки задается вопрос, был ли изменен столбец is_working. Если условие истинно, обновите все дочерние категории (рекурсивные).