在表上实现语句级触发器时,是否可以获取所有受影响行的OLD和NEW记录?

Ada*_*ter 13 sql oracle triggers

在Oracle中,您可以通过在FOR EACH ROW语句中指定子句来编写行级触发器CREATE TRIGGER:

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;
Run Code Online (Sandbox Code Playgroud)

这样的触发允许您在查看之前之后的每个受影响的行(版本:OLD:NEW分别).例如,以下语句将导致此触发器对每一行执行一次MY_TABLE:

UPDATE MY_TABLE SET some_other_column = 'bar';
Run Code Online (Sandbox Code Playgroud)

通过消除该FOR EACH ROW子句,触发器变为语句级别触发器.这意味着每个语句只执行一次,无论语句有多少行(如果有)受影响.不幸的是,语句级触发器没有:OLD:NEW变量可用(因为受影响的行数很多).

是否可以在语句级触发器中获取所有受影响行的:OLD:NEW值?我有一些处理,我宁愿每个语句只发生一次.

jos*_*989 10

一种方法是由Justin Cave建议的方法,用于将行级别触发器中的信息存储在单独的包集合中.

如果您使用的是11g,那么正确的方法是使用复合触发器.这样可以避免创建单独的包来保存密钥集合 - 它可以在触发器本身中完成,


Jus*_*ave 8

不直接,没有.

标准方法是"三触发解决方案"(当您尝试解决变异表问题时更常用)

  1. 创建一个包含表的键集合的包
  2. 创建初始化集合的before语句触发器
  3. 创建将键插入集合的行级触发器.
  4. 创建一个after语句触发器,该触发器使用集合中的键进行处理

显然,在您的情况下,如果您的行级触发器没有导致变异表错误,这可能只会增加进程的复杂性.

正如josephj1989在下面指出的那样,如果你碰巧使用11g,你可以使用复合触发器来简化这一点.您仍将声明一个集合,在行级触发器主体中填充该集合,并在语句级触发器中处理该集合.但是只有一个对象可以创建和管理而不是多个对象.