在表上实现语句级触发器时,是不是可以获取所有受影响行的 OLD 和 NEW 记录?
Posted
技术标签:
【中文标题】在表上实现语句级触发器时,是不是可以获取所有受影响行的 OLD 和 NEW 记录?【英文标题】:When implementing a statement-level trigger on a table, is it possible to obtain the OLD and NEW records for all affected rows?在表上实现语句级触发器时,是否可以获取所有受影响行的 OLD 和 NEW 记录? 【发布时间】:2011-08-19 19:07:16 【问题描述】:在 Oracle 中,您可以通过在 CREATE TRIGGER
语句中指定 FOR EACH ROW
子句来编写行级触发器:
CREATE TRIGGER MY_FANCY_TRIGGER
BEFORE UPDATE ON MY_TABLE
FOR EACH ROW
BEGIN
IF :OLD.my_id_column > 4 AND :NEW.some_other_column <> 'foo' THEN
-- ...
END IF;
END;
这样的触发器允许您查看每个受影响行的之前和之后版本(分别为:OLD
和:NEW
)。例如,以下语句将导致此触发器对MY_TABLE
中的每一行执行一次:
UPDATE MY_TABLE SET some_other_column = 'bar';
通过消除FOR EACH ROW
子句,触发器变为语句 级触发器。这意味着它每条语句只执行一次,无论有多少行(如果有)受语句影响。不幸的是,语句级触发器没有可用的:OLD
和:NEW
变量(因为受影响的行数很多不同)。
是否可以在语句级触发器中获取 所有 受影响行的 :OLD
和 :NEW
值?我有一些处理,我希望每个语句只发生一次。
【问题讨论】:
【参考方案1】:Justin Cave 建议的一种方法是将信息存储在单独的包集合中的行级触发器中。
如果您使用的是 11g,那么正确的方法是使用复合触发器。这避免了创建单独的包来保存键集合 - 它可以在触发器本身中完成,
【讨论】:
我接受这个答案作为首选的前进解决方案。【参考方案2】:不直接,不。
标准方法是“三触发解决方案”(在您尝试解决变异表问题时更常用)
-
创建一个包,其中包含您的表的键集合
创建一个用于初始化集合的 before 语句触发器
创建将键插入集合的行级触发器。
创建使用集合中的键进行处理的后语句触发器
显然,在您的情况下,如果您的行级触发器没有导致变异表错误,这可能只会增加流程的复杂性。
正如 josephj1989 在下面指出的那样,如果您碰巧使用的是 11g,则可以使用compound triggers 来简化这一点。您仍将声明一个集合,将集合填充到行级触发器主体中,并在语句级触发器中处理该集合。但是将只创建和管理一个对象,而不是多个对象。
【讨论】:
有趣的方法。你是对的,它确实增加了复杂性,但它可能是我唯一的选择(10g)。 statement-level 触发器会在 row-level 触发器之前触发吗? 语句前触发器在行级插入/更新/删除触发器之前触发。在行级插入/更新/删除触发器之后触发语句后触发器。以上是关于在表上实现语句级触发器时,是不是可以获取所有受影响行的 OLD 和 NEW 记录?的主要内容,如果未能解决你的问题,请参考以下文章