简体   繁体   English

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

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

In Oracle, you can write a row-level trigger by specifying the FOR EACH ROW clause in the CREATE TRIGGER statement: 在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;

Such a trigger allows you to view the before and after versions of each affected row ( :OLD and :NEW respectively). 这样的触发器使您可以查看每个受影响的行的之前之后的版本(分别为:OLD:NEW )。 For example, the following statement will cause this trigger to execute once for each row in MY_TABLE : 例如,以下语句将使此触发器对MY_TABLE每一行执行一次:

UPDATE MY_TABLE SET some_other_column = 'bar';

By eliminating the FOR EACH ROW clause, the trigger becomes a statement -level trigger. 通过消除FOR EACH ROW子句,触发器将成为语句级触发器。 This means that it only be executed once per statement , regardless of how many rows (if any) were affected by the statement. 这意味着每个语句仅执行一次,无论该语句影响多少行(如果有)。 Unfortunately, statement-level triggers do not have the :OLD and :NEW variables available (because the number of affected rows many vary). 不幸的是,语句级触发器没有可用的:OLD:NEW变量(因为受影响的行数很多)。

Is it possible to obtain the :OLD and :NEW values for all affected rows inside a statement-level trigger? 是否可以在语句级触发器内获取所有受影响行的:OLD:NEW值? I have some processing that I would prefer to only occur once per statement. 我有一些处理,我希望每个语句只出现一次。

One approach is the one suggested by Justin Cave to store away information in row level triggers in a separate package collections. 贾斯汀·凯夫(Justin Cave)提出的一种方法是,将行级触发器中的信息存储在单独的程序包集合中。

If you are using 11g then the right approach will be to use Compound triggers. 如果您使用的是11g,则正确的方法是使用复合触发器。 This avoids the creation of separate package to hold the keys collection- it can be done in the trigger itself, 这样可以避免创建用于保存键集合的单独程序包-可以在触发器本身中完成操作,

Not directly, no. 不直接,不。

The standard approach is the "three-trigger solution" (more commonly used when you're trying to work around a mutating table problem) 标准方法是“三触发解决方案”(在尝试解决变异表问题时更常用)

  1. Create a package that contains a collection of keys to your table 创建一个包含表的键集合的包
  2. Create a before statement trigger that initializes the collection 创建一个before语句触发器来初始化集合
  3. Create a row-level trigger that inserts the keys into the collection. 创建一个行级触发器,将键插入集合中。
  4. Create an after statement trigger that uses the keys in the collection to do its processing 创建一个after语句触发器,该触发器使用集合中的键进行处理

Obviously, in your case, this probably just adds complexity to the process if your row-level trigger isn't causing a mutating table error. 显然,在您的情况下,如果您的行级触发器没有引起变异表错误,则这可能只会增加流程的复杂性。

As josephj1989 points out below, if you happen to be using 11g, you can use compound triggers to simplify this a bit. 正如josephj1989在下面指出的那样,如果您恰好使用11g,则可以使用复合触发器来简化此操作。 You'll still declare a collection, populate the collection in a row-level trigger body, and process the collection in the statement-level trigger. 您仍将声明一个集合,将该集合填充到行级触发器主体中,并在语句级触发器中处理该集合。 But there will be just one object to create and manage rather than multiple objects. 但是,只有一个对象可以创建和管理,而不是多个对象。

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

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