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

Sql 在表上实现语句级触发器时,是否可以获取所有受影响行的新旧记录?,sql,oracle,triggers,Sql,Oracle,Triggers,在Oracle中,您可以通过在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; 通过消除每行的子句,触发器成为

在Oracle中,您可以通过在
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;
通过消除每行的
子句,触发器成为语句级触发器。这意味着无论有多少行(如果有的话)受语句影响,每个语句只能执行一次。遗憾的是,语句级触发器没有可用的
:OLD
:NEW
变量(因为受影响的行数各不相同)

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

不是直接的,不是

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

  • 创建包含表的键集合的包
  • 创建用于初始化集合的before语句触发器
  • 创建将键插入集合的行级触发器
  • 创建after语句触发器,该触发器使用集合中的键进行处理
  • 显然,在您的情况下,如果行级触发器没有导致变异表错误,那么这可能只会增加流程的复杂性


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

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


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

    有趣的方法。你说得对,它确实增加了复杂性,但它可能是我唯一的选择(10g)。语句级触发器是否在行级触发器之前触发?before语句触发器在insert/update/delete触发器之前的行级触发器之前触发。在insert/update/delete触发器之后的行级别之后触发after语句触发器。我接受这个答案作为首选的前进解决方案。
    UPDATE MY_TABLE SET some_other_column = 'bar';