如何防止 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 中的递归触发器调用的主要内容,如果未能解决你的问题,请参考以下文章

防止触发器的相互递归执行?

如何将 DB2 触发器转换为 SQL Server?

DB2数据库中的序列和触发器??

如何防止ajax调用两次触发

DB2:忽略更新触发器中的列

想写一个DB2触发器,几张表有关联,修改其中一张主表中的某一个字段,其他关联表中的该字段也跟着联动修改