Предотвратить рекурсивный триггер в PostgreSQL - PullRequest
21 голосов
/ 02 апреля 2009

Как предотвратить рекурсивное выполнение триггера? Допустим, я хочу построить «древовидное» описание в плане счетов. Итак, что я делаю, когда новая запись вставляется / обновляется, я обновляю родительскую запись down_qty, так что это будет запускать триггер обновления рекурсивно.

Прямо сейчас мой код в порядке - я поместил это в UPDATE первую строку триггера:

-- prevents recursive trigger
if new.track_recursive_trigger <> old.track_recursive_trigger then
    return new;
end if;

И это пример кода из моего триггера, когда мне нужно обновить количество родительской записи:

update account_category set 
    track_recursive_trigger = track_recursive_trigger + 1, -- i put this line to prevent recursive trigger
    down_qty = down_qty - (old.down_qty + 1)
where account_category_id = m_parent_account;

Я думаю, есть ли способ в PostgreSQL обнаруживать рекурсивный триггер без введения нового поля, что-то аналогичное MSSQL trigger_nestlevel.

[EDIT]

Я зацикливаюсь внутри дерева, мне нужно всплыть down_qty каждого account_category обратно к его корню. Например, я вставляю новую категорию аккаунта, для этого нужно увеличить down_qty родительского элемента account_category, аналогично, когда я изменяю родителя категории аккаунта account_category, мне нужно уменьшить значение down_qty на account_category '. s предыдущий родитель account_category. Хотя я думаю, что это возможно, я не позволяю PostgreSQL выполнять рекурсивный триггер. Я использовал MSSQL раньше, когда уровень рекурсивной глубины триггера ограничен только 16 уровнями.

Ответы [ 4 ]

72 голосов
/ 10 января 2013

Это то, что я делаю в PostgreSQL 9.2, хотя должен признать, что этот подход не был задокументирован. Здесь задокументирована функция pg_trigger_depth() , которую я использую для различения исходных и вложенных вызовов в триггере.

CREATE TRIGGER trg_taxonomic_positions
AFTER INSERT OR UPDATE OF taxonomic_position
ON taxon_concepts
FOR EACH ROW
WHEN (pg_trigger_depth() = 0)
EXECUTE PROCEDURE trg_taxonomic_positions()
9 голосов
/ 02 апреля 2009

В pg, вы можете отслеживать рекурсию триггера.

Если триггерная функция выполняет SQL команды, то эти команды могут огонь снова срабатывает. Это известно как каскадные триггеры. Там нет прямого ограничение по количеству каскадов уровни. Для каскадов возможно вызвать рекурсивный вызов тот же триггер; например, ВСТАВКА триггер может выполнить команду, которая вставляет дополнительный ряд в та же таблица, вызывая триггер INSERT быть уволенным снова. Это спусковой крючок ответственность программиста, чтобы избежать бесконечная рекурсия в таких сценариях.

http://www.postgresql.org/docs/8.3/static/trigger-definition.html

3 голосов
/ 14 октября 2010

В начале определения триггера вы можете отключить триггеры для этой конкретной таблицы и снова включить их в конце (и убедиться, что исключение не прекращает выполнение раньше ожидаемого!). Это имеет много глубоких отверстий, но может работать для некоторых легких реализаций. Обратите внимание, что для этой реализации вам также потребуются полномочия для отключения триггеров.

2 голосов
/ 11 января 2013

Чтобы избежать неограниченной рекурсии, см. мой ответ здесь . Как прокомментировали другие, если ваша структура данных является истинным деревом (у корня (ов) не будет родительского (ых)), и рекурсия всегда остановит в корне (ах). Для узлов только с одним родительским указателем единственным способом для неограниченной рекурсии будет наличие циклов. (метод в моей ссылке посетит любой узел самое большее один раз)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...