在表上实现语句级触发器时,是不是可以获取所有受影响行的 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 记录?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle中触发器有几种,用法与SQL Server一样吗?谢谢

行级触发器

行级触发器和语句级触发器

如何在 2 个视图控制器上实现广告

如何在受保护的 java 类上实现接口

PHP判断sql语句是不是执行成功