Learning Objectives – after this chapter you will be able to:
  • Explain what a database trigger is and where it is used.
  • Differentiate statement-level, row-level, BEFORE and AFTER triggers (12 combinations).
  • Create triggers with CREATE TRIGGER, WHEN, OF and REFERENCING.
  • Use the correlation names :NEW and :OLD and the predicates INSERTING, UPDATING, DELETING.
  • Write INSTEAD OF triggers on views; enable, disable and drop triggers.
What is a Database Trigger?

A database trigger is a PL/SQL block executed on an event in the database – a particular data manipulation of a table (INSERT, UPDATE or DELETE). Triggers are used to:

  • implement complex business rules that integrity constraints cannot;
  • audit – keep track of changes made to a table;
  • automatically perform an action when another action takes place.

Like stored procedures, but procedures are called explicitly, whereas triggers are fired implicitly by Oracle; their execution is transparent to users.

Types of Triggers
TypeFiredTypical use
Statement-level (default)Once per DML statement, however many rows are affected; no access to NEW/OLDRules not related to data, e.g. no changes to BATCHES after 9 P.M.
Row-level (FOR EACH ROW)Once for every affected row (100 rows → 100 times)Checking validity of data; rules that constraints cannot express
BEFOREBefore the command executesValidation, e.g. preventing a deletion
AFTERAfter the triggering action completesActions after the row is changed

Combinations: BEFORE statement, BEFORE row, AFTER statement, AFTER row – each for INSERT, DELETE and UPDATE = 12 triggers.

Creating a Trigger
CREATE [OR REPLACE] TRIGGER triggername {BEFORE | AFTER} {DELETE | INSERT | UPDATE [OF columns]} [OR {DELETE | INSERT | UPDATE [OF columns]}] ... ON table [FOR EACH ROW [WHEN condition]] [REFERENCING [OLD AS old] [NEW AS new]] PL/SQL block
  • FOR EACH ROW makes it a row-level trigger; otherwise it is statement-level.
  • WHEN fires the trigger only when the condition is true (row triggers only), e.g. when (new.amount > 1000).
  • OF columns – only updates of these columns fire the trigger.
  • REFERENCING renames the correlation names (to avoid conflicts with table names).
  • Naming convention used: table_event_type, e.g. STUDENTS_BI_ROW = STUDENTS, Before Insert, ROW.
Row-level and statement-level triggers
create or replace trigger students_bi_row
before insert on students
for each row
begin
   if :new.dj > sysdate then
      raise_application_error(-20002, 'Date of joining cannot be after system date.');
   end if;
end;
/
create or replace trigger payments_bi_row
before insert on payments
for each row
declare
   v_dueamt number(5);
begin
   v_dueamt := getdueamt(:new.rollno);           -- function from Chapter 19
   if :new.amount > v_dueamt then
      raise_application_error(-20112, 'Amount being paid is more than what is to be paid');
   end if;
end;
/
create or replace trigger payments_biud           -- statement-level
before insert or update or delete on payments
begin
   if to_char(sysdate,'DY') = 'SUN' then
      raise_application_error(-20111, 'No changes can be made on sunday.');
   end if;
end;
  • Valid statements in a trigger body: DML commands and SELECT INTO; it may call stored procedures, functions and packages.
  • USER_TRIGGERS lists triggers; TRIGGER_BODY is a LONG column – increase SQL*Plus SET LONG (default 80) to see all of it.
Correlation Names :NEW and :OLD
CommandNEWOLD
INSERTYesNo (no old values)
UPDATEYes (after change)Yes (before change)
DELETENo (no new values)Yes
Preventing a change to AMOUNT
create or replace trigger payments_bu_row
before update on payments
for each row
begin
   if :new.amount <> :old.amount then
      raise_application_error(-20113,
        'Amount cannot be changed. Please delete and reinsert the row, if required');
   end if;
end;
INSTEAD OF Triggers

Defined on relational views and object views that cannot be modified directly by DML. Instead of executing the DML on the view, Oracle runs the INSTEAD OF trigger. Inserting into the join view NEWSTUDENT (STUDENTS + PAYMENTS) normally fails with ORA-01779; the trigger below inserts into both tables.

create or replace trigger newstudent_it_bi_row
instead of insert on newstudent
for each row
begin
   insert into students (rollno, bcode, name, gender, dj)
   values (:new.rollno, :new.bcode, :new.name, :new.gender, sysdate);
   insert into payments values (:new.rollno, sysdate, :new.amount);
end;
/
insert into newstudent values (15,'Joe','b2','m',2000);   -- one row in each table
Which Command Fired the Trigger?

When one trigger handles several commands, the conditional predicates INSERTING, DELETING and UPDATING tell which one fired it.

Audit log of changes to COURSES
create or replace trigger courses_biud_row
before insert or delete or update on courses
for each row
begin
   if inserting then
      insert into courses_log values (1, :new.ccode, sysdate, user);
   elsif deleting then
      insert into courses_log values (2, :old.ccode, sysdate, user);
   else
      insert into courses_log values (3, :old.ccode, sysdate, user);
   end if;
end;
Enabling, Disabling and Dropping
alter trigger payments_bu_row disable;
alter trigger payments_bu_row enable;
alter table students disable all triggers;
drop trigger payments_bu_row;

Disabling triggers speeds up large data changes (e.g. update students set name = upper(name)) because the trigger code is not executed; a disabled trigger does not fire until enabled.

Key Takeaways
  • Triggers fire implicitly on INSERT/UPDATE/DELETE; statement-level is the default.
  • Row triggers (FOR EACH ROW) can use :NEW and :OLD and a WHEN condition.
  • INSTEAD OF triggers make non-updatable views updatable.
  • INSERTING/UPDATING/DELETING identify the firing command; ALTER TRIGGER enables/disables.
Chapter 20 Notes (PDF)
ch20.pdf 11 pages 290 KB Open in PDF Viewer (Free Tool)

Your browser cannot show this PDF here. Open Chapter 20 Notes (PDF)

ch20.pdfKeys: ← → page · + − zoom · F full screen
Question / Answer (15 questions)

Moderate-level questions based on the Chapter 20 notes (PDF). Click a question to see the answer.

Answer : A database trigger is a PL/SQL block that is executed on an event in the database – a particular data manipulation of a table such as inserting, deleting or updating a row. Triggers are executed automatically by Oracle and their execution is transparent to users.

Answer : To implement complex business rules that cannot be implemented using integrity constraints, to audit the process (keep track of changes made to a table), and to automatically perform an action when another related action takes place, e.g. updating a table whenever a row is inserted into another.

Answer : Both are PL/SQL blocks stored in the database, but stored procedures are called explicitly, whereas triggers are called implicitly by Oracle when the concerned event occurs.

Answer : A statement-level trigger fires only once for a DML statement irrespective of the number of rows affected and cannot access NEW and OLD; it is the default and suits rules not related to data. A row-level trigger, created with FOR EACH ROW, fires once for each affected row (100 rows → 100 times) and is used to check the validity of data.

Answer : A BEFORE trigger fires before the INSERT, UPDATE or DELETE is executed and is commonly used to check the validity of data, e.g. to prevent a deletion. An AFTER trigger fires after the triggering action is completed, e.g. after the row is inserted.

Answer : Four timing/level combinations – before statement, before row, after statement and after row – each of which can be associated with INSERT, DELETE and UPDATE, giving a total of 12 triggers.

Answer : The name of the trigger, the table it is associated with, when it is fired (BEFORE or AFTER), the command that invokes it (INSERT, UPDATE [OF columns] or DELETE), whether it is a row-level trigger (FOR EACH ROW), an optional condition to filter rows (WHEN), and the PL/SQL block to execute.

Answer : WHEN fires the trigger only when the given condition is satisfied and can be used only with row triggers (e.g. only when the new AMOUNT is more than 1000). OF specifies the columns whose update fires the trigger. REFERENCING gives new names instead of the default correlation names OLD and NEW, mainly to avoid name conflicts with tables.

Answer : It is a BEFORE INSERT, row-level trigger on STUDENTS (name = table + BI for before insert + ROW). It checks whether :NEW.DJ (date of joining of the row being inserted) is greater than SYSDATE and, if so, raises an error with RAISE_APPLICATION_ERROR(-20002, ...).

Answer : DML commands and SELECT INTO are the valid statements; the trigger can also use existing stored procedures, functions and packages. USER_TRIGGERS lists triggers; its TRIGGER_BODY column is of LONG type, so the SQL*Plus variable LONG (default 80) should be set larger to see the full body.

Answer : NEW refers to the new values and OLD to the old (existing) values of the row in a row-level trigger. For INSERT only NEW is available, for DELETE only OLD is available, and for UPDATE both are available – OLD before the change and NEW after the change.

Answer : A BEFORE UPDATE row-level trigger compares the values: IF :NEW.amount <> :OLD.amount THEN RAISE_APPLICATION_ERROR(-20113, 'Amount cannot be changed...'); END IF; – if they differ, the value is being changed and the trigger fails.

Answer : It is defined on relational views and object views to modify views that cannot be directly modified by DML. Instead of executing the DML command on the view, Oracle invokes the INSTEAD OF trigger – e.g. inserting into the join view NEWSTUDENT (which normally gives ORA-01779) inserts one row into STUDENTS and one into PAYMENTS.

Answer : By using the conditional predicates INSERTING, DELETING and UPDATING in the trigger body, e.g. IF inserting THEN log 1 ELSIF deleting THEN log 2 ELSE log 3 – as used by COURSES_BIUD_ROW to write to COURSES_LOG.

Answer : ALTER TRIGGER name DISABLE / ENABLE disables or enables one trigger; ALTER TABLE table DISABLE ALL TRIGGERS disables all triggers of a table; DROP TRIGGER name removes it. Disabling improves performance when a large amount of data is modified, because the trigger code is not executed.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which data dictionary view contains information about triggers?

Show Answer

Correct Answer : A. USER_TRIGGERS
USER_TRIGGERS lists the triggers of the current account, including TRIGGER_BODY.

Q2. What is the default type of trigger?

Show Answer

Correct Answer : B. Statement-level
Without FOR EACH ROW the trigger is a statement-level trigger.

Q3. In a DELETE trigger, which correlation name is available?

Show Answer

Correct Answer : C. OLD only
A deleted row has no new values, so only OLD is available.

Q4. How many trigger combinations of timing, level and DML command are possible as per the notes?

Show Answer

Correct Answer : D. 12
Before/after × statement/row = 4, each for INSERT, DELETE and UPDATE = 12.

Q5. Which trigger type is used to make a non-updatable view accept DML?

Show Answer

Correct Answer : A. INSTEAD OF trigger
INSTEAD OF triggers run in place of the DML on relational or object views.

Bibliography/References

The chapter notes PDF is the course study material and is credited to its author below. The explanations, questions and MCQs on this page are original study aids written for this course from the topics covered in that PDF. The other works are cited for verification and further reading. Oracle, SQL*Plus and PL/SQL are trademarks of Oracle Corporation; other names belong to their respective owners.

  1. Srikanth, P. (n.d.). Oracle For Beginners (chapter notes – the PDF shown on each chapter page). Srikanth Technologies. http://www.srikanthtechnologies.com/
  2. Oracle Corporation. (n.d.). Oracle Database PL/SQL Language Reference, 19c. https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/
  3. Oracle Corporation. (n.d.). Oracle Database Concepts, 19c. https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/
  4. Feuerstein, S., & Pribyl, B. (2014). Oracle PL/SQL Programming (6th ed.). O’Reilly Media.