如何防止 DB2 中的递归触发器调用
Posted
技术标签:
【中文标题】如何防止 DB2 中的递归触发器调用【英文标题】:How to prevent recursive trigger call in DB2 【发布时间】:2012-12-12 18:28:44 【问题描述】:我有一个更新语句,嵌套在更新触发器中:
CREATE TRIGGER "BAD_RECURSIVE_TRIGGER"
AFTER UPDATE ON "MYTABLE"
REFERENCING NEW AS NEW_ROW
FOR EACH ROW
WHEN (NEW_ROW.ORDER IS NOT NULL)
BEGIN ATOMIC
IF <SOMECONDITION> THEN
UPDATE "MYTABLE" SET ORDER=ORDER+1 // This "update" fires the recursion.
WHERE <OTHERCONDITION>
END IF;
END;
我想阻止触发器的递归执行,这是在 DB2 (v9.7) 上,我已经看到 SQL-Server 和 ORACLE 数据库的类似问题:
Prevent recursive trigger in PostgreSQL
How do I prevent a database trigger from recursing?
但我找不到通过 DB2 防止这种情况发生的方法。有没有办法防止 DB2 上的递归触发器调用?
【问题讨论】:
必须是AFTER UPDATE
吗?如果触发器发生在实际更新之前,并在此时修改ORDER
,会发生什么情况?而且我会假设您只想更新“当前”行,但该语句将更新 整个 表...或者,仅在 ORDER
hasn' 时更新t 从它的当前值更改(如果新值与旧的表内值相同)。
@Clockwork-Muse,期望的行为是:如果“这条记录被更新”,那么“更新其他记录”(来自同一个表)。问题是,在第一个“更新触发器”上,它会进行另一次更新,再次触发触发器。而且似乎没有办法知道是否是第一个电话,这可以解决我的问题。我已经为此发布了另一个问题:***.com/questions/13845776/…,但我仍然愿意接受任何其他好的选择。
... 为什么要更新表中的其他记录?您要解决的实际问题是什么?该语句将成为一个巨大的瓶颈,因为您最终将获得对表的串行访问。
我将尝试总结原始要求:在表上有一个“ORDER”列,以允许用户根据需要修改项目的“顺序”,该顺序应保留在数据库中因为将基于它进行查询。必须保持顺序(作为连续的数字列表)。如此小的“列表”将保存在数据库中。例如:有一个订单的记录列表:1、2、3、4。如果用户插入一条订单 = 2 的新记录,记录 3 和 4 将更新为“订单 = 订单 + 1”。删除记录时的类似行为(“上”记录的顺序将更新为“order = order - 1”)。
【参考方案1】:
创建触发无级联之前更新...
【讨论】:
不幸的是,无法在内部创建带有“update”语句的“before update”触发器,并且在内部创建带有“update”的“after trigger”不允许使用“NO CASCADE” " 声明 (pic.dhe.ibm.com/infocenter/db2luw/v9r7),这很可悲,因为他们似乎特别想避免我正在寻找的行为 =(【参考方案2】:您不希望将整数类型的列用于这样的事情,因为它需要(最终)重新排序给定“组”中的所有其他条目。
当您希望允许重新定位条目时,请改用 floating 类型。这将允许通过简单地修改所需条目来更改顺序。 有这样的声明:
UPDATE Example SET ordering = (((SELECT COALESCE(ordering, FLOAT_MAX_VALUE)
FROM Example
WHERE id = @entry_above_insertion_point)
-
(SELECT COALESCE(ordering, FLOAT_MIN_VALUE)
FROM Example
WHERE id = @entry_below_insertion_point))
/ 2)
+ (SELECT COALESCE(ordering, FLOAT_MIN_VALUE)
FROM Example
WHERE id = @entry_below_insertion_point)
WHERE id = @entry
这会将条目放置在两个当前条目之间的“中间”。由于浮点的工作方式,您希望从 0 开始值;怀疑您是否需要对数据进行规范化。
【讨论】:
以上是关于如何防止 DB2 中的递归触发器调用的主要内容,如果未能解决你的问题,请参考以下文章