Управление с использованием алгоритма Adjacency List
Задача
"Прозрачное" управление, совместно с алгоритмом Adjacency List.
На самом деле, мне лично смешивание Materialized Path и Adjacency List при использовании ltree представляется сомнительным решением, особенно учитывая то, что в большинстве случаем материализованный путь составляется из ID узлов, и ID родителя получить не представляется сложной задачей. Тем не менее, определенные плюсы от этого есть, а именно:
Прямая связь с родителем и возможность навесить FOREIGN KEY;
Возможность просто указывать id родителя не тратя время на формирование материализованного пути изменяегмого узла;
Универсальная хранимая процедура
Вообще идея подобной процедуры не моя, а моего коллеги, но он так до конца её и не реализовал. Эту реализацию я сделал в том числе и для него.
Таблица должна иметь следующие свойства:
материализованных путь формируется из id узлов;
имеется возможность хранения нескольких независимых деревьев;
В таблице должны присутсвовать следующие обязательные поля:
Где:
id - собственно id;
pid - id родителя, NULL если узел корневой;
root - идентификатор дерева, обязательное поле. Если в таблице будет храниться одно дерево, то для него можно поставить значение по умолчанию, например, 1;
path - материализованный путь;
Соответственно, внешний ключ на каскадное обновление и удаление для поля pid.
Сама хранимая процедура выглядит так:
Ввиду того, что данная процедура будет использоваться при любом изменении таблицы, опрерации в ней разделены по использованию переменных NEW и OLD, так как при обращении к переменной NEW во время удаления даст ошибку, так как и обращение к переменной OLD во время вставки.
В процедуре предусмотрена работа с переменными таблицами и схемами, в зависимости от триггера её (процедуру) вызвавшего, что дает возможность использовать данную процедуру в нескольких таблицах одновременно. Но данное решение не совсем оптимально в так как запросы внутри процедуры не компилируются сразу а в процессе выполнения.
Создаем триггер для таблицы.
Увы, при изменении подчиненности узла, вышеуказанный триггер не распространится на детей, соответсвенно потребуется произвести ручное обновление (внешний ключ не поможет так как id не обновляется):
То что удаление подчиненных записей производится до удаления родительской тоже не совсем хорошо, но опять же, все зависит от того, насколько часто производится удаление.