防止PostgreSQL中的递归触发器

时间:2009-04-02 06:50:22

标签: postgresql recursion

如何防止触发器的递归执行?假设我想在账户图表上构建一个“树形”描述。所以我所做的是当插入/更新新记录时,我更新父记录的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

[编辑]

我在树内循环,我需要将每个down_qty的{​​{1}}冒泡回到它的根。例如,我插入一个新的帐户类别,它需要增加其父account_category的{​​{1}},同样当我更改帐户类别的父down_qty时,我需要递减{{ 1 {}} account_category的上一个父account_category。虽然我认为它可以,但我不是让PostgreSQL做递归触发器。我之前使用的是MSSQL,其中触发递归深度级别仅限于down_qty级别。

4 个答案:

答案 0 :(得分:72)

这就是我在PostgreSQL 9.2中所做的,虽然我必须承认我没有发现这种方法的记录。有一个函数pg_trigger_depth() documented here,我用它来区分触发器中的原始和嵌套调用。

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()

答案 1 :(得分:9)

在pg中,由你来跟踪触发器递归。

  

如果触发器函数执行SQL   然后这些命令可能会命令   火再次触发。这被称为   级联触发器。没有直接的   限制级联数量   水平。级联有可能   导致递归调用   同样的触发;例如,INSERT   触发器可能会执行一个命令   在...中插入一行   同一个表,导致INSERT触发器   被解雇了。这是触发器   程序员有责任避免   在这种情况下无限递归。

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

答案 2 :(得分:3)

在触发器定义的开始时,您可以禁用该特定表上的触发器,并在最后重新启用它们(并确保异常不会在预期之前终止执行!)。这有很多深洞,但可能适用于一些轻量级实现。请注意,对于此实现,您还需要特权来禁用触发器。

答案 3 :(得分:2)

要避免无限制的递归,请参阅 my answer here。正如其他人所评论的那样,如果您的数据结构是真树(根将没有父节点),并且递归将始终在根节点停止。对于只有一个父指针节点,无限递归的唯一方法是存在循环。 (我的链接中的方法最多会访问的任何节点