如何防止触发器的递归执行?假设我想在账户图表上构建一个“树形”描述。所以我所做的是当插入/更新新记录时,我更新父记录的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
级别。
答案 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。正如其他人所评论的那样,如果您的数据结构是真树(根将没有父节点),并且递归将始终在根节点停止。对于只有一个父指针的节点,无限递归的唯一方法是存在循环。 (我的链接中的方法最多会访问的任何节点)