在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
值?我有一些处理,我希望每个语句只发生一次。
答案 0 :(得分:10)
Justin Cave建议将一种方法存储在单独的包集合中的行级触发器中。
如果你使用11g,那么正确的方法是使用复合触发器。这样可以避免创建单独的包来保存密钥集合 - 它可以在触发器本身中完成,
答案 1 :(得分:8)
不直接,没有。
标准方法是“三触发解决方案”(当您尝试解决变异表问题时更常用)
显然,在您的情况下,如果您的行级触发器没有导致变异表错误,这可能只会增加进程的复杂性。
正如josephj1989在下面指出的那样,如果你碰巧使用了11g,你可以使用compound triggers来简化这一点。您仍将声明一个集合,在行级触发器主体中填充该集合,并在语句级触发器中处理该集合。但是只有一个对象可以创建和管理而不是多个对象。