AdTech AI PostgreSQL О компании
PostgreSQL · Деревья 14 февраля, 2025 Сергей Томулевич

Nested Sets. Использование триггеров в PostgreSQL

Реализация Nested Sets через триггеры PostgreSQL. Триггеры на INSERT, UPDATE, DELETE с поддержкой parent_id и left_key.

Задача

Управление древовидными структурами в PostgreSQL предполагает компромисс: структуры Nested Sets удобны для выборок, но сложны в управлении, тогда как idparent_id удобны для управления, но требуют рекурсивных запросов при выборках.

Два подхода реализации:

Таблица

CREATE TABLE ns_tree (
    id                      SERIAL,
    left_key                INTEGER       NOT NULL,
    right_key               INTEGER       NOT NULL,
    level                   INTEGER       NOT NULL DEFAULT 0,
    tree                    INTEGER       NOT NULL,
    parent_id               INTEGER       NOT NULL DEFAULT 0,
    _trigger_lock_update    BOOLEAN       NOT NULL DEFAULT FALSE,
    _trigger_for_delete     BOOLEAN       NOT NULL DEFAULT FALSE,
    field_1                 ...,
    PRIMARY KEY (id)
);

Вспомогательная функция блокировки

CREATE OR REPLACE FUNCTION lock_ns_tree(integer)
    RETURNS boolean AS
$BODY$
DECLARE tree_id ALIAS FOR $1;
    _id INTEGER;
BEGIN
    SELECT id
        INTO _id
        FROM ns_tree
        WHERE tree = tree_id FOR UPDATE;
    RETURN TRUE;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Создание записи

Триггер поддерживает три варианта добавления узла: по parent_id, по left_key, в конец дерева.

Триггер BEFORE INSERT выполняет:

Полный код триггера — на оригинальной странице.

Изменение записи

Триггер BEFORE UPDATE обрабатывает перемещение узлов:

Удаление записи

Два варианта триггеров AFTER DELETE:

Вариант 1 — с потомками: удаляет узел и всю его ветку, затем сдвигает оставшиеся ключи.

Вариант 2 — без потомков (смещение на уровень вверх): при удалении узла его потомки поднимаются на уровень родителя.

Индексы

Рекомендуемые индексы:

Связанные материалы

Готовы посчитать собственный стек? Расскажем, какие модули и какая нагрузка нужны под вашу задачу.

to@prototypes.ventures