Oracle Row-level Triggers

Summary: in this tutorial, you will learn about Oracle row-level triggers and how to use the CREATE TRIGGER statement to create a new row-level trigger.

Introduction to Oracle row-level triggers

Row-level triggers fires once for each row affected by the triggering event such as INSERT, UPDATE, or DELETE.

Row-level triggers are useful for data-related activities such as data auditing and data validation.

To create a new row-level trigger, you use the CREATE TRIGGER statement with the FOR EACH ROW clause.

CREATE OR REPLACE TRIGGER trigger_name BEFORE | AFTER INSERT OR DELETE OR UPDATE OF column1, column2, … ON table_name FOR EACH ROW REFERENCING OLD AS old_name NEW AS new_name WHEN (condition) DECLAREBEGINEXCEPTIONEND;
Code language: SQL (Structured Query Language) (sql)

The features which are applicable to the statement-level triggers are also available the row-level trigger:

  • Use raise_application_error() to raise a user-defined exception
  • Check if the current event is INSERT, UPDATE, and DELETE using the INSERTING or DELETING or UPDATING.

On top of that, row-level triggers allow you to track the BEFORE and AFTER values.

The :OLD & :NEW column values

Because row-level triggers execute within the context of a single row, you can access the old and new column values using the following syntax:

:OLD.column_name :NEW.column_name
Code language: SQL (Structured Query Language) (sql)

For example, this statement checks the value of the credit_limit column to see if the new credit is greater than the current credit:

IF :NEW.credit_limit > :OLD.credit_limit THEN -- carry an action END;
Code language: SQL (Structured Query Language) (sql)

This table illustrates the availability of :NEW and :OLD variables by the triggering event:

Triggering Event:NEW:OLD
INSERTYesNo
UPDATEYesYes
DELETENoyes

Modifying :OLD & :NEW values

A BEFORE row-level trigger can modify the new column values, but an AFTER row-level trigger cannot.

Correlation names

OLD and NEW are the default correlation names. But you can override them using the REFERENCING clause.

When you reference OLD and NEW in the trigger body, you must precede them with a colon (:) because OLD and NEW are external variable references.

Performance consideration

A row-level trigger fires each time a row is affected by a triggering event. For example, if you update 1000 rows in a table, the trigger will fire 1000 times, which potentially cause a performance issue.

To specify a condition of when to fire the trigger, you can use the WHEN clause. For example, the following trigger only fires when you update credit for a customer with the new credit is greater than 10,000:

CREATE OR REPLACE TRIGGER BEFORE UPDATE OF credit_limit ON customers FOR EACH ROW WHEN NEW.credit_limit > 10000; ...
Code language: SQL (Structured Query Language) (sql)

In some situations, using the condition in the WHEN can significantly improve the performance of the database.

Note that you can use both OLD and NEW in the WHEN clause. In addition, you don’t use a colon (:) as the prefix for these variables.

Oracle row-level trigger example

We’ll use the customers table from the sample database for demonstration:

customers table

The following example creates a row-level trigger that prevents users from updating credit for a customer if the new credit increases to more than double:

CREATE OR REPLACE TRIGGER customers_update_credit_trg BEFORE UPDATE OF credit_limit ON customers FOR EACH ROW WHEN (NEW.credit_limit > 0) BEGIN -- check the credit limit IF :NEW.credit_limit >= 2 * :OLD.credit_limit THEN raise_application_error(-20101,'The new credit ' || :NEW.credit_limit || ' cannot increase to more than double, the current credit ' || :OLD.credit_limit); END IF; END;
Code language: SQL (Structured Query Language) (sql)

First, specify the name of the trigger:

CREATE OR REPLACE TRIGGER customers_update_credit_trg
Code language: SQL (Structured Query Language) (sql)

Next, set the triggering event is BEFORE UPDATE of the credit_limit column on the customers table.

BEFORE UPDATE OF credit_limit ON customers
Code language: SQL (Structured Query Language) (sql)

Then, use the FOR EACH ROW to specify that the trigger is a row-level trigger.

FOR EACH ROW
Code language: SQL (Structured Query Language) (sql)

After that, specify the condition that fires trigger only when the new credit is greater than zero in the WHEN clause:

WHEN (NEW.credit_limit > 0)
Code language: SQL (Structured Query Language) (sql)

Finally, check the new credit from the :NEW variable with the current credit from the :OLD variable, call the procedure raise_application_error to raise an error if it is.

IF :NEW.credit_limit >= 2 * :OLD.credit_limit THEN raise_application_error(-20101,'The new credit ' || :NEW.credit_limit || ' cannot increase to more than double, the current credit ' || :OLD.credit_limit); END IF;
Code language: SQL (Structured Query Language) (sql)

Testing the trigger

First, find the credit limit of the customer id 10:

SELECT credit_limit FROM customers WHERE customer_id = 10;
Code language: SQL (Structured Query Language) (sql)

Here is the output:

CREDIT_LIMIT ------------ 2000
Code language: SQL (Structured Query Language) (sql)

Second, update the credit of the customer 10 to 5000:

UPDATE customers SET credit_limit = 5000 WHERE customer_id = 10;
Code language: SQL (Structured Query Language) (sql)

The output is as follows:

ORA-20101: The new credit 5000 cannot increase more than double, the current credit 2000 ORA-06512: at "OT.CUSTOMERS_UPDATE_CREDIT_TRG", line 4 ORA-04088: error during execution of trigger 'OT.CUSTOMERS_UPDATE_CREDIT_TRG'
Code language: SQL (Structured Query Language) (sql)

It means that the trigger customers_update_credit_trg has been fired as expected.

In this tutorial, you have learned about Oracle row-level triggers and how to use the CREATE TRIGGER statement to create a new row-level trigger.

Was this tutorial helpful?