繁体   English   中英

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

[英]When implementing a statement-level trigger on a table, is it possible to obtain the OLD and NEW records for all affected rows?

在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值? 我有一些处理,我希望每个语句只出现一次。

贾斯汀·凯夫(Justin Cave)提出的一种方法是,将行级触发器中的信息存储在单独的程序包集合中。

如果您使用的是11g,则正确的方法是使用复合触发器。 这样可以避免创建用于保存键集合的单独程序包-可以在触发器本身中完成操作,

不直接,不。

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

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

显然,在您的情况下,如果您的行级触发器没有引起变异表错误,则这可能只会增加流程的复杂性。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM