简体   繁体   中英

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:

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). For example, the following statement will cause this trigger to execute once for each row in MY_TABLE :

UPDATE MY_TABLE SET some_other_column = 'bar';

By eliminating the FOR EACH ROW clause, the trigger becomes a statement -level trigger. 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).

Is it possible to obtain the :OLD and :NEW values for all affected rows inside a statement-level trigger? 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.

If you are using 11g then the right approach will be to use Compound triggers. 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
  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

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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