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

时间:2011-05-05 23:24:00

标签: 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;

这样的触发器允许您查看每个受影响行(<{1}}和:OLD的之前的之后的。例如,以下语句将导致此触发器对:NEW中的每一行执行一次:

MY_TABLE

通过消除UPDATE MY_TABLE SET some_other_column = 'bar'; 子句,触发器变为语句 -level触发器。这意味着它只能执行一次每个语句,无论该语句有多少行(如果有)受影响。遗憾的是,语句级触发器没有可用的FOR EACH ROW:OLD变量(因为受影响的行数很多)。

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

2 个答案:

答案 0 :(得分:10)

Justin Cave建议将一种方法存储在单独的包集合中的行级触发器中。

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

答案 1 :(得分:8)

不直接,没有。

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

  1. 创建一个包含表格键集合的包
  2. 创建初始化集合的before语句触发器
  3. 创建一个将键插入集合的行级触发器。
  4. 创建一个使用集合中的键进行处理的after语句触发器
  5. 显然,在您的情况下,如果您的行级触发器没有导致变异表错误,这可能只会增加进程的复杂性。

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