Oracle® Database PL/SQL Language Reference 11g Release 1 (11.

1) Part Number B28370-05

Home Book ContentsIndex Master Contact List Index Us
PDF · Mobi · ePub

Previous Next

9 Using Triggers
A trigger is a named PL/SQL unit that is stored in the database and executed (fired) in response to a specified event that occurs in the database. Topics:
            

Overview of Triggers Guidelines for Designing Triggers Privileges Required to Use Triggers Creating Triggers Coding the Trigger Body Compiling Triggers Modifying Triggers Debugging Triggers Enabling Triggers Disabling Triggers Viewing Information About Triggers Examples of Trigger Applications Responding to Database Events Through Triggers

Overview of Triggers
A trigger is a named program unit that is stored in the database and fired (executed) in response to a specified event. The specified event is associated with either a table, a view, a schema, or the database, and it is one of the following:
  

A database manipulation (DML) statement (DELETE, INSERT, or UPDATE) A database definition (DDL) statement (CREATE, ALTER, or DROP) A database operation (SERVERERROR, LOGON, LOGOFF, STARTUP, or SHUTDOWN)

The trigger is said to be defined on the table, view, schema, or database. Topics:

Trigger Types

  

Trigger States Data Access for Triggers Uses of Triggers

Trigger Types
A DML trigger is fired by a DML statement, a DDL trigger is fired by a DDL statement, a DELETE trigger is fired by a DELETE statement, and so on. An INSTEAD OF trigger is a DML trigger that is defined on a view (not a table). The database fires the INSTEAD OF trigger instead of executing the triggering DML statement. For more information, see Modifying Complex Views (INSTEAD OF Triggers). A system trigger is defined on a schema or the database. A trigger defined on a schema fires for each event associated with the owner of the schema (the current user). A trigger defined on a database fires for each event associated with all users. A simple trigger can fire at exactly one of the following timing points:
   

Before the triggering statement executes After the triggering statement executes Before each row that the triggering statement affects After each row that the triggering statement affects

A compound trigger can fire at more than one timing point. Compound triggers make it easier to program an approach where you want the actions you implement for the various timing points to share common data. For more information, see Compound Triggers.

Trigger States
A trigger can be in either of two states: Enabled. An enabled trigger executes its trigger body if a triggering statement is entered and the trigger restriction (if any) evaluates to TRUE. Disabled. A disabled trigger does not execute its trigger body, even if a triggering statement is entered and the trigger restriction (if any) evaluates to TRUE. By default, a trigger is created in enabled state. To create a trigger in disabled state, use the DISABLE clause of the CREATE TRIGGER statement. See Also: CREATE TRIGGER Statement

Data Access for Triggers

When a trigger is fired, the tables referenced in the trigger action might be currently undergoing changes by SQL statements in other users' transactions. In all cases, the SQL statements running within triggers follow the common rules used for standalone SQL statements. In particular, if an uncommitted transaction has modified values that a trigger being fired either must read (query) or write (update), then the SQL statements in the body of the trigger being fired use the following guidelines:
 

Queries see the current read-consistent materialized view of referenced tables and any data changed within the same transaction. Updates wait for existing data locks to be released before proceeding.

Uses of Triggers
Triggers supplement the standard capabilities of your database to provide a highly customized database management system. For example, you can use triggers to:
           

Automatically generate derived column values Enforce referential integrity across nodes in a distributed database Enforce complex business rules Provide transparent event logging Provide auditing Maintain synchronous table replicates Gather statistics on table access Modify table data when DML statements are issued against views Publish information about database events, user events, and SQL statements to subscribing applications Restrict DML operations against a table to those issued during regular business hours Enforce security authorizations Prevent invalid transactions

Caution: Triggers are not reliable security mechanisms, because they are programmatic and easy to disable. For high assurance security, use Oracle Database Vault. For more information, see Oracle Database Vault Administrator's Guide.

Guidelines for Designing Triggers
Use the following guidelines when designing triggers:
 

Use triggers to guarantee that when a specific operation is performed, related actions are performed. Do not define triggers that duplicate database features. For example, do not define triggers to reject bad data if you can do the same checking through constraints.

If you use a LOGON trigger to monitor logons by users. Oracle strongly recommends that you use triggers to constrain data input only in the following situations: o o o To enforce referential integrity when child and parent tables are on different nodes of a distributed database To enforce complex business rules not definable using integrity constraints When a required referential integrity rule cannot be enforced using the following integrity constraints:  NOT NULL. They are executed for every user every time the event occurs on which the trigger is created. Privileges Required to Use Triggers To create a trigger in your schema:   You must have the CREATE TRIGGER system privilege One of the following must be true: o You own the table specified in the triggering statement o You have the ALTER privilege for the table specified in the triggering statement . The size of the trigger cannot exceed 32K. If the logic for your trigger requires much more than 60 lines of PL/SQL code. global operations that must fire for the triggering statement. Otherwise. regardless of which user or database application issues the statement.   Use triggers only for centralized.    Use triggers on DATABASE judiciously. and include a WHEN OTHERS exception in the exception-handling part.Although you can use both triggers and integrity constraints to define and enforce any type of integrity rule. If you use a LOGON trigger only to execute a package (for example. Do not create recursive triggers. For example. and the trigger itself issues an UPDATE statement on the employees table. put the exception-handling part in the package instead of in the trigger. if you create an AFTER UPDATE statement trigger on the employees table. the trigger fires recursively until it runs out of memory. an unhandled exception might block all connections to the database. UNIQUE      PRIMARY KEY FOREIGN KEY CHECK DELETE CASCADE DELETE SET NULL  Limit the size of triggers. put most of the code in a stored subprogram and invoke the subprogram from the trigger. an application contextsetting package). include an exception-handling part in the trigger.

which creates a simple trigger for the emp table.EMPNO > 0) DECLARE sal_diff number. dbms_output. If this privilege is later revoked. use the CREATE TRIGGER statement. use the DISABLE clause of the CREATE TRIGGER statement. When using the CREATE TRIGGER statement with an interactive tool. BEGIN sal_diff := :NEW.o You have the ALTER ANY TABLE system privilege To create a trigger in another schema. By default.sal). such as SQL*Plus or Enterprise Manager.:OLD.SAL. Example 9-1 CREATE TRIGGER Statement CREATE OR REPLACE TRIGGER Print_salary_changes BEFORE DELETE OR INSERT OR UPDATE ON emp FOR EACH ROW WHEN (NEW. or to reference a table in another schema from a trigger in your schema:   You must have the CREATE ANY TRIGGER system privilege. you must have the ADMINISTER DATABASE TRIGGER privilege.sal). a trigger is created in enabled state. The statements in the trigger body operate under the privilege domain of the trigger owner. For information about trigger states.put_line(' Difference ' || sal_diff). / See Also: CREATE TRIGGER Statement The trigger in Example 9-1 fires when DML operations are performed on the table. END. Creating Triggers To create a trigger. The object privileges to the schema objects referenced in the trigger body must be granted to the trigger owner explicitly (not through a role). To create a trigger on the database. .put('Old salary: ' || :OLD. you can drop the trigger but not alter it. not the privilege domain of the user issuing the triggering statement (this is similar to the privilege model for stored subprograms). You must have the EXECUTE privilege on the referenced subprograms or packages. put a single slash (/) on the last line. as in Example 9-1. To create a trigger in disabled state. You can choose what combination of operations must fire the trigger.SAL . dbms_output. dbms_output. see Overview of Triggers.put(' New salary: ' || :NEW.

DATABASE. The options include DELETE. a table and a trigger can have the same name (however. The table. it can access the new values before they go into the table. view. but not examine the data for each row. The following sections use Example 9-1 to show how parts of a trigger are specified. it might be executed multiple times.column_name. For additional examples of CREATE TRIGGER statements. following SQL statement fires the trigger once for each row that is updated.Because the trigger uses the BEFORE keyword. You might use the AFTER keyword if you want the trigger to query or change the same table. Because the trigger uses the FOR EACH ROW clause. The CREATE (or CREATE OR REPLACE) statement fails if any errors exist in the PL/SQL block. and the difference between them: UPDATE emp SET sal = sal + 500. or DDL event that fires the trigger body. After the trigger is created. Trigger names need not be unique with respect to other schema objects.00 WHERE deptno = 10. such as tables. One. and UPDATE. because triggers can only do that after the initial changes are applied and the table is back in a consistent state. this is not recommended). views. which specifies:   The SQL statement. . INSERT. such as when updating or deleting multiple rows. or SCHEMA on which the trigger is defined. the old salary. two. For example. When Does the Trigger Fire? A trigger fires based on a triggering statement. Topics:         Naming Triggers When Does the Trigger Fire? Controlling When a Trigger Fires (BEFORE and AFTER Options) Modifying Complex Views (INSTEAD OF Triggers) Firing Triggers One or Many Times (FOR EACH ROW Option) Firing Triggers Based on Conditions (WHEN Clause) Compound Triggers Ordering of Triggers Naming Triggers Trigger names must be unique with respect to other triggers in the same schema. or all three of these options can be included in the triggering statement specification. to avoid confusion. You might omit this clause if you just want to record the fact that the operation occurred. in each case printing the new salary. see Examples of Trigger Applications. database event. and can change the values if there is an easily-corrected error by assigning to :NEW. and subprograms.

or UPDATE on the emp table. triggers are disabled before the load. then import creates and loads it before any triggers are defined.. if a view is specified in the triggering statement. then import loads rows into existing tables. (For direct loads. ... The previous example of the PRINT_SALARY_CHANGES trigger can include a column list in the triggering statement. BEFORE DELETE OR INSERT OR UPDATE OF ename ON emp . INTO emp VALUES ( . If the column specified in the UPDATE OF clause is an object column. If IGNORE=Y.. then the trigger also fires if any of the attributes of the object are modified.. If the table does not exist... and indexes are updated to account for the imported data. How Column Lists Affect UPDATE Triggers An UPDATE statement might include a list of columns. If the INSTEAD OF option is used.. INTO emp SELECT . .. INSERT. so again no triggers fire.) The IGNORE parameter of the IMP statement determines whether triggers fire during import operations:    If IGNORE=N (default) and the table already exists. then only the INSTEAD OF option can be used. For example: . FROM .. conversely. If a triggering statement includes a column list. the trigger fires only when one of the specified columns is updated.Note: Exactly one table or view can be specified in the triggering statement.. Note:    You cannot specify a column list for UPDATE with INSTEAD OF triggers. ). Any existing triggers fire. Do Import and SQL*Loader Fire Triggers? INSERT triggers fire during SQL*Loader conventional loads. You cannot specify UPDATE OF clauses on collection columns. then import does not change the table and no existing triggers fire. If a triggering statement omits a column list. In Example 9-1. Any of the following statements trigger the PRINT_SALARY_CHANGES trigger: DELETE INSERT INSERT UPDATE FROM emp. . the PRINT_SALARY_CHANGES trigger fires after any DELETE. A column list cannot be specified for INSERT or DELETE triggering statements.. then the triggering statement must specify a view. the trigger fires when any column of the associated table is updated. emp SET .

The rollback to savepoint does not undo changes to any package variables referenced in the trigger. using the row ID. affected data blocks must be read (logical read. the BEFORE statement trigger fires again. In a CREATE TRIGGER statement. do not create triggers that depend on the order in which rows are processed. the BEFORE or AFTER option is specified just before the triggering statement. Include a counter variable in your package to detect this situation. For the options of compound triggers. When a statement in a trigger body causes another trigger to fire. The BEFORE or AFTER option in the CREATE TRIGGER statement specifies exactly when to fire the trigger body in relation to the triggering statement that is being run. Therefore. For example. Each time the statement is restarted. see Compound Triggers. do not assign a value to a global package variable in a row trigger if the current value of the global variable is dependent on the row being processed by the row trigger. Ordering of Triggers A relational database does not guarantee the order of rows processed by a SQL statement. if global package variables are updated within a trigger.Controlling When a Trigger Fires (BEFORE and AFTER Options) Note: This topic applies only to simple triggers. then the database performs a transparent ROLLBACK to SAVEPOINT and restarts the update. and perform operations. the triggers are said to be cascading. Note: BEFORE row triggers are slightly more efficient than AFTER row triggers. With AFTER row triggers. the PRINT_SALARY_CHANGES trigger in the previous example is a BEFORE trigger. You can limit the . Also. you use BEFORE or AFTER triggers to achieve the following results:   Use BEFORE row triggers to modify the row before the row data is written to disk. For example. then it is best to initialize those variables in a BEFORE statement trigger. In general. the data blocks must be read only once for both the triggering statement and the trigger. Use AFTER row triggers to obtain. The database allows up to 32 triggers to cascade at simultaneously. This can occur many times before the statement completes successfully. not physical read) once for the trigger and then again for the triggering statement. with BEFORE row triggers. If an UPDATE or DELETE statement detects a conflict with a concurrent UPDATE. Alternatively. An AFTER row trigger fires when the triggering statement results in ORA-2292.

The trigger must determine what operation was intended and perform UPDATE. See Also: CREATE TRIGGER Statement for more information about ordering of triggers and the FOLLOWS clause Modifying Complex Views (INSTEAD OF Triggers) Note: INSTEAD OF triggers can be defined only on views. Without the FOLLOWS clause. Some views are inherently updatable. because a cursor must be opened for every execution of a trigger. as set by the most recently fired UPDATE or INSERT trigger. unlike other types of triggers. and DELETE statements against the view. and the INSTEAD OF trigger works invisibly in the background to make the right actions take place. If you have multiple triggers of the same type on the same table. using multiple triggers of the same type allows the modular installation of applications that have triggers on the same tables. and the order in which they execute is important. INSERT. use the FOLLOWS clause. and DELETE statements. not on tables. Each trigger can see the old and new values. and the new values are the current values. unpredictable order. Although any trigger can run a sequence of operations either inline or by invoking subprograms. the database fires the trigger instead of executing the triggering statement. INSTEAD OF triggers can only be activated for each row. With an INSTEAD OF trigger. The old values are the original values.number of trigger cascades by using the initialization parameter OPEN_CURSORS. These triggers are invoked INSTEAD OF triggers because. but others are not because they were created with one or more of the constructs listed in Views that Require INSTEAD OF Triggers. The database executes all triggers of the same type before executing triggers of a different type. See Also: . INSERT. INSERT. Each subsequent trigger sees the changes made by the previously fired triggers. INSTEAD OF triggers provide a transparent way of modifying views that cannot be modified directly through UPDATE. An updatable view is one that lets you perform DML on the underlying table. or DELETE operations directly on the underlying tables. Any view that contains one of those constructs can be made updatable by using an INSTEAD OF trigger. the database chooses an arbitrary. you can write normal UPDATE.

If the object is read only. or START WITH clause A collection expression in a SELECT list A subquery in a SELECT list A subquery designated WITH READ ONLY Joins. unless the object view is modifiable. These triggers provide a way of updating elements of the nested table. The row correlation variables inside the trigger correspond to the nested table element. The INSTEAD OF trigger body must enforce the check. ORDER BY. They fire for each nested table element being modified. This type of trigger also provides an additional correlation name for accessing the parent row that contains the nested table being modified. you must specify INSTEAD OF triggers. MODEL. The BEFORE and AFTER options cannot be used for triggers defined on views. then you can only update the view with an UPDATE statement that does not refer to any of the pseudocolumns or expressions. with some exceptions. or DELETE statements if the view query contains any of the following constructs:         A set operator A DISTINCT operator An aggregate or analytic function A GROUP BY. CONNECT BY. See Also: Oracle Call Interface Programmer's Guide To modify an object materialized by an object view in the client-side object cache and flush it back to the persistent store. INSERT.Firing Triggers One or Many Times (FOR EACH ROW Option) Note:    The INSTEAD OF option can be used only for triggers defined on views. then it is not necessary to define triggers to pin it. as documented in Oracle Database Administrator's Guide If a view contains pseudocolumns or expressions. Triggers on Nested Table View Columns INSTEAD OF triggers can also be created over nested table view columns. Views that Require INSTEAD OF Triggers A view cannot be modified by UPDATE. INSTEAD OF triggers provide the means to modify object view instances on the client-side through OCI calls. The CHECK option for views is not enforced when inserts or updates to the view are done using INSTEAD OF triggers. Note: .

The CAST (MULTISET) operator creates a multiset of employees for each department. and the emp table is filled with the correct values. :Employee. The following example shows how an insert trigger might be written: CREATE OR REPLACE TRIGGER Dept_emplist_tr INSTEAD OF INSERT ON NESTED TABLE Emplist OF Dept_view REFERENCING NEW AS Employee PARENT AS Department FOR EACH ROW BEGIN -.Empno. consider a department view that contains a nested table of employees.Salary) FROM emp e WHERE e.Empname. Resp_dept NUMBER). Example: INSTEAD OF Trigger Note: You might need to set up the following data structures for this example to work: CREATE TABLE Project_tab ( Prj_level NUMBER.Sal. They do not fire when a DML statement is performed on the view.:Employee. d. 'John Glenn'.These triggers:   Can only be defined over nested table columns in views. Projno NUMBER. CREATE TABLE emp ( .Deptno). which is the nested table of employees. CREATE OR REPLACE VIEW Dept_view AS SELECT d.Deptno = d.Deptno) AS Amp_list_ Emplist FROM dept d. The :department. END. define an INSTEAD OF trigger over the column to handle the operation.Insert on nested table translates to insert on base table: INSERT INTO emp VALUES (:Employee. :Department. e. To modify the emplist column.Deptno.Ename.Dept_type. e. CAST (MULTISET ( SELECT e. d.Empno. For example: INSERT INTO TABLE (SELECT d.Emplist FROM Dept_view d WHERE Deptno = 10) VALUES (1001.deptno correlation variable in this example has the value 10.Dname. 10000). Any INSERT into the nested table fires the trigger. Fire only when the nested table elements are modified using the TABLE clause. For example.

projno = :n.projno CREATE OR REPLACE TRIGGER manager_info_insert INSTEAD OF INSERT ON manager_info REFERENCING NEW AS n -.empno. p.Empno Ename Job Mgr Hiredate Sal Comm Deptno NUMBER NOT NULL. BEGIN SELECT COUNT(*) INTO rowcnt FROM emp WHERE empno = :n.ename.2). END.dept_type WHERE dept.deptno.prj_level = :n. ELSE UPDATE Project_tab SET Project_tab.ename) VALUES (:n.dept_type).new manager information FOR EACH ROW DECLARE rowcnt number. NUMBER(4).empno = :n.deptno = p.deptno.empno. END IF.2). Loc VARCHAR2(13). SELECT COUNT(*) INTO rowcnt FROM dept WHERE deptno = :n. :n. SELECT COUNT(*) INTO rowcnt FROM Project_tab WHERE Project_tab. VARCHAR2(9). Dname VARCHAR2(14). :n. p. d. NUMBER(2) NOT NULL).ename = :n.prj_level). ELSE UPDATE dept SET dept. ELSE UPDATE emp SET emp. VARCHAR2(10). e. NUMBER(7.deptno. IF rowcnt = 0 THEN INSERT INTO emp (empno. dept_type) VALUES(:n. d.projno.projno. Dept_type NUMBER).dept_type = :n. FROM emp e.deptno. :n.projno = :n.projno.prj_level WHERE Project_tab. NUMBER(7. IF rowcnt = 0 THEN INSERT INTO Project_tab (projno.ename WHERE emp.empno. DATE. CREATE TABLE dept ( Deptno NUMBER(2) NOT NULL. . END IF.prj_level.ename).dept_type. The following example shows an INSTEAD OF trigger for inserting rows into the MANAGER_INFO view.empno.resp_dept. IF rowcnt = 0 THEN INSERT INTO dept (deptno. dept d. CREATE OR REPLACE VIEW manager_info AS SELECT e.mgr_no AND d. prj_level) VALUES(:n. Project_tab p WHERE e.deptno = :n.empno = d. Mgr_no NUMBER. END IF.

For the options of compound triggers. If you specify FOR EACH ROW. then the trigger fires once for each row of the table that is affected by the triggering statement.SAL. For example. see Compound Triggers.The actions shown for rows being inserted into the MANAGER_INFO view first test to see if appropriate rows already exist in the base tables from which MANAGER_INFO is derived. as appropriate. VARCHAR2(20)). :NEW. If there are five employees in department 20. The actions then insert new rows or update existing rows.Empno. Then. Action) VALUES (:NEW. END. The absence of the FOR EACH ROW option indicates that the trigger fires only once for each applicable statement. because five rows are affected. NUMBER. The following trigger fires only once for each UPDATE of the emp table: CREATE OR REPLACE TRIGGER Log_emp_update AFTER UPDATE ON emp .Sal > 1000) BEGIN INSERT INTO Emp_log (Emp_id. 'NEW SAL'). define the following trigger: CREATE OR REPLACE TRIGGER Log_salary_increase AFTER UPDATE ON emp FOR EACH ROW WHEN (NEW. Log_date. assume that the table Emp_log was created as follows: CREATE TABLE Emp_id Log_date New_salary Action Emp_log ( NUMBER. Similar triggers can specify appropriate actions for UPDATE and DELETE. but not separately for each row affected by the statement. SYSDATE.0 WHERE Deptno = 20. then the trigger fires five times when this statement is entered. DATE. you enter the following SQL statement: UPDATE emp SET Sal = Sal + 1000. New_salary. Then. Firing Triggers One or Many Times (FOR EACH ROW Option) Note: This topic applies only to simple triggers. The FOR EACH ROW option determines whether the trigger is a row trigger or a statement trigger.

However. a trigger restriction can be included in the definition of a row trigger by specifying a Boolean SQL expression in a WHEN clause. the trigger body is not run if the new value of Empno is zero. 'emp COMMISSIONS CHANGED'). then the expression in the WHEN clause is evaluated for each row that the trigger affects. Note: You cannot specify the WHEN clause for INSTEAD OF triggers. in the PRINT_SALARY_CHANGES trigger. the triggering statement is not rolled back if the expression in a WHEN clause evaluates to FALSE). then the trigger body executes on behalf of that row. Topics:   Why Use Compound Triggers? Compound Trigger Sections . If included.BEGIN INSERT INTO Emp_log (Log_date. The expression in a WHEN clause must be a SQL expression. The statement level triggers are useful for performing validation checks for the entire statement. Action) VALUES (SYSDATE. as with nulls). You cannot use a PL/SQL expression (including user-defined functions) in the WHEN clause. The expression in a WHEN clause of a row trigger can include correlation names. In more realistic examples. If the expression evaluates to TRUE for a row. Note: A WHEN clause cannot be included in the definition of a statement trigger. and it cannot include a subquery. or negative. if the expression evaluates to FALSE or NOT TRUE for a row (unknown. you might test if one column value is less than another. Firing Triggers Based on Conditions (WHEN Clause) Optionally. Compound Triggers A compound trigger can fire at more than one timing point. For example. which are explained later. The evaluation of the WHEN clause does not have an effect on the execution of the triggering SQL statement (in other words. NULL. END. then the trigger body does not execute for that row.

even when the triggering statement causes an error. This approach was both cumbersome to program and subject to memory leak when the triggering statement caused an error and the after-statement trigger did not fire. 12 END BEFORE STATEMENT. Example 9-2 Compound Trigger SQL> CREATE OR REPLACE TRIGGER compound_trigger 2 FOR UPDATE OF salary ON employees 3 COMPOUND TRIGGER 4 5 -. 23 24 AFTER STATEMENT IS 25 BEGIN 26 NULL. A compound trigger has an optional declarative part and a section for each of its timing points (see Example 9-2). 18 19 AFTER EACH ROW IS 20 BEGIN 21 NULL. 8 9 BEFORE STATEMENT IS 10 BEGIN 11 NULL. 17 END BEFORE EACH ROW. you had to model the common state with an ancillary package. 27 END AFTER STATEMENT. 22 END AFTER EACH ROW. To achieve the same effect with simple triggers. 28 END compound_trigger. 7 threshold CONSTANT SIMPLE_INTEGER := 200.Declarative part (optional) 6 -. 13 14 BEFORE EACH ROW IS 15 BEGIN 16 NULL. All of these sections can access a common PL/SQL state.    Triggering Statements of Compound Triggers Compound Trigger Restrictions Compound Trigger Example Using Compound Triggers to Avoid Mutating-Table Error Why Use Compound Triggers? The compound trigger makes it easier to program an approach where you want the actions you implement for the various timing points to share common data. The common state is established when the triggering statement starts and is destroyed when the triggering statement completes.Variables declared here have firing-statement duration. 29 / Trigger created. .

It cannot have multiple sections for the same timing point. Table 9-1 summarizes the timing point sections of a compound trigger that can be defined on a table. If a timing-point section is absent. Variables and subprograms declared in this section have firing-statement duration. Timing-point sections must appear in the order shown in Table 9-1. A compound trigger defined on a view has an INSTEAD OF EACH ROW timing-point section. A compound trigger defined on a table has one or more of the timing-point sections described in Table 9-1. When the trigger fires. Table 9-1 Timing-Point Sections of a Compound Trigger Defined Timing Point Before the triggering statement executes After the triggering statement executes Before each row that the triggering statement affects After each row that the triggering statement affects Section BEFORE STATEMENT AFTER STATEMENT BEFORE EACH ROW AFTER EACH ROW Any section can include the functions Inserting. A timing-point section cannot be enclosed in a PL/SQL block. Updating.SQL> Two common reasons to use compound triggers are:   To accumulate rows destined for a second table so that you can periodically bulk-insert them (as in Compound Trigger Example) To avoid the mutating-table error (ORA-04091) (as in Using Compound Triggers to Avoid Mutating-Table Error) Compound Trigger Sections A compound trigger has a declarative part and at least one timing-point section. and Applying. See Also: . nothing happens at its timing point. the declarative part executes before any timing-point sections execute. and no other timing-point section. The optional declarative part (the first part) declares variables and subprograms that timing-point sections can use. Deleting.

The declarative part cannot include PRAGMA AUTONOMOUS_TRANSACTION. Compound Trigger Restrictions      The body of a compound trigger must be a compound trigger block. and you get no benefit from using a compound trigger. see Using FORALL and BULK COLLECT Together. therefore. . If the triggering statement of a compound trigger is an INSERT statement that includes a subquery. For example. it cannot have an exception section. A compound trigger body cannot have an initialization block. For example. respectively). For more information about using the BULK COLLECT clause with the FORALL statement. If a section includes a GOTO statement. the compound trigger retains some of its performance benefit.   An exception that occurs in one section must be handled in that section. This is not a problem. the target of the GOTO statement must be in the same section. a FORALL statement that contains an INSERT statement simply performs a single-row insertion operation many times.CREATE TRIGGER Statement for more information about the syntax of compound triggers Triggering Statements of Compound Triggers The triggering statement of a compound trigger must be a DML statement. the trigger never fires. c2.c1 > 0 For each row of Source whose column c1 is greater than zero. the BEFORE STATEMENT and AFTER STATEMENT sections each execute only once (before and after the INSERT statement executes. If the triggering statement affects no rows. without the BULK COLLECT clause. However. suppose that a compound trigger is triggered by the following statement: INSERT INTO Target SELECT c1. It cannot transfer control to another section. A compound trigger must be defined on either a table or a view. and the compound trigger has neither a BEFORE STATEMENT section nor an AFTER STATEMENT section. c3 FROM Source WHERE Source. the BEFORE EACH ROW and AFTER EACH ROW sections of the compound trigger execute. because the BEFORE STATEMENT section always executes exactly once before any other timing-point section executes. This is why it is important to use the BULK COLLECT clause with the FORALL statement. A compound trigger must be a DML trigger. It is when the triggering statement affects many rows that a compound trigger has a performance benefit.

Solution: Define a compound trigger on updates of the table hr. after the compound trigger fires. :NEW.Choose small threshhold value to show how example works: threshhold CONSTANT SIMPLE_INTEGER := 7. the triggering statement rolls back due to a DML exception: o Local variables declared in the compound trigger sections are re-initialized. The firing order of compound triggers is not guaranteed. If compound triggers are ordered using the FOLLOWS option. Compound Trigger Example Scenario: You want to record every change to hr. idx SIMPLE_INTEGER := 0.employees. salaries salaries_t. and :PARENT cannot appear in the declarative part.Declarative Part: -. Their firing can be interleaved with the firing of simple triggers. therefore.salaries is more efficient than inserting them individually. because they are state variables. salary NUMBER(8. Only the BEFORE EACH ROW section can change the value of :NEW.employees. o Side effects from firing the compound trigger are not rolled back. You do not need a BEFORE STATEMENT section to initialize idx or salaries. CONSTRAINT pk_employee_salaries PRIMARY KEY (employee_id.     :OLD. PROCEDURE flush_array IS .employees. or the AFTER STATEMENT section.2) NOT NULL. CONSTRAINT fk_employee_salaries FOREIGN KEY (employee_id) REFERENCES employees (employee_id) ON DELETE CASCADE) / CREATE OR REPLACE TRIGGER maintain_employee_salaries FOR UPDATE OF salary ON employees COMPOUND TRIGGER -.salary in a new table. bulk-inserting rows into employee. and if the target of FOLLOWS does not contain the corresponding section as source code. A single UPDATE statement will update many rows of the table hr. which are initialized each time the trigger fires (even when the triggering statement is interrupted and restarted). If. change_date DATE NOT NULL. TYPE salaries_t IS TABLE OF employee_salaries%ROWTYPE INDEX BY SIMPLE_INTEGER. the BEFORE STATEMENT section. the ordering is ignored. Example 9-3 Compound Trigger Records Changes to One Table in Another Table CREATE TABLE employee_salaries ( employee_id NUMBER NOT NULL. employee_salaries. and any values computed thus far are lost. change_date). as in Example 9-3.

END. . DBMS_OUTPUT. IF idx >= threshhold THEN flush_array()..employee_id.delete(). salaries. salaries(idx). salaries(idx).salary.SLEEP(2). END AFTER EACH ROW.AFTER EACH ROW Section: AFTER EACH ROW IS BEGIN idx := idx + 1.change_date := SYSDATE(). idx := 0.PUT_LINE('Flushed ' || n || ' rows'). salaries(idx). END AFTER STATEMENT. BEGIN FORALL j IN 1.employee_id := :NEW. -.n INSERT INTO employee_salaries VALUES salaries(j).salary := :NEW. / /* Increase salary of every employee in department 50 by 10%: */ UPDATE employees SET salary = salary * 1. / /* Increase salary of every employee in department 50 by 5%: */ UPDATE employees SET salary = salary * 1.1 WHERE department_id = 50 / /* Wait two seconds: */ BEGIN DBMS_LOCK.05 WHERE department_id = 50 / Using Compound Triggers to Avoid Mutating-Table Error You can use compound triggers to avoid the mutating-table error (ORA-04091) described in Trigger Restrictions on Mutating Tables. END maintain_employee_salaries.count().AFTER STATEMENT Section: AFTER STATEMENT IS BEGIN flush_array(). END flush_array. END IF. -.n CONSTANT SIMPLE_INTEGER := salaries.

and as such.1. Solution: Define a compound trigger on updates of the table hr.:Old. FOR j IN 1.COUNT() LOOP Department_Avg_Salaries(Department_IDs(j)) := Avg_Salaries(j). Example 9-4 Compound Trigger that Avoids Mutating-Table Error CREATE OR REPLACE TRIGGER Check_Employee_Salary_Raise FOR UPDATE OF Salary ON Employees COMPOUND TRIGGER Ten_Percent CONSTANT NUMBER := 0. it can include SQL and . Coding the Trigger Body Note: This topic applies primarily to simple triggers. The state variables are initialized each time the trigger fires (even when the triggering statement is interrupted and restarted). AFTER EACH ROW IS BEGIN IF :NEW. The trigger body is either a CALL subprogram (a PL/SQL subprogram. Department_IDs FROM Employees e GROUP BY e.employees. TYPE Department_IDs_t IS TABLE OF Employees. -1) BULK COLLECT INTO Avg_Salaries.Department_IDs. This rule must be enforced by a trigger.Department_ID.Salary .Salary%TYPE INDEX BY VARCHAR2(80). NVL(e. END IF.Department_ID. END AFTER EACH ROW.Salary).Scenario: A business rule states that an employee's salary increase must not exceed 10% of the average salary for the employee's department. The body of a compound trigger has a different format (see Compound Triggers).Salary%TYPE. END LOOP. END BEFORE STATEMENT. 'Raise too big'). END Check_Employee_Salary_Raise. or a Java subprogram encapsulated in a PL/SQL wrapper) or a PL/SQL block.. Avg_Salaries Salaries_t. TYPE Salaries_t IS TABLE OF Employees.Department_ID%TYPE. Department_IDs Department_IDs_t. BEFORE STATEMENT IS BEGIN SELECT AVG(e. as in Example 9-4.Department_ID) THEN Raise_Application_Error(-20000.Salary > Ten_Percent*Department_Avg_Salaries(:NEW. Department_Salaries_t. TYPE Department_Salaries_t Department_Avg_Salaries IS TABLE OF Employees.

/ Although triggers are declared using PL/SQL. The body of the trigger includes an exception-handling part.io.sql.* oracle.CHAR)'. Ename VARCHAR2) IS language Java name 'thjvTriggers.NUMBER.PL/SQL statements.beforeDelete (oracle. If the trigger body for a row trigger is a PL/SQL block (not a CALL subprogram). oracle. they can call subprograms in other languages. Example 9-6 Invoking a Java Subprogram from a Trigger CREATE OR REPLACE PROCEDURE Before_delete (Id IN NUMBER. :OLD. END. 'Unexpected error: '|| DBMS_Utility. which includes a WHEN OTHERS exception that invokes RAISE_APPLICATION_ERROR. NEW. which can specify correlation names OLD.Format_Error_Stack). EXCEPTION WHEN OTHERS THEN RAISE_APPLICATION_ERROR (-20000. These statements are executed if the triggering statement is entered and if the trigger restriction (if any) evaluates to TRUE.check_user. DELETING.sql. and UPDATING See Also: CREATE TRIGGER Statement for syntax and semantics of this statement The LOGON trigger in Example 9-5 executes the procedure sec_mgr.* java.Ename) / The corresponding Java file is thjvTriggers.sql.* oracle.Id. and PARENT Conditional predicates INSERTING.* . Example 9-5 Monitoring Logons with a Trigger CREATE OR REPLACE TRIGGER check_user AFTER LOGON ON DATABASE BEGIN sec_mgr.check_user after a user logs onto the database.sql. CREATE OR REPLACE TRIGGER Pre_del_trigger BEFORE DELETE ON Tab FOR EACH ROW CALL Before_delete (:OLD. it can include the following constructs:   REFERENCING clause. The trigger in Example 9-6 invokes a Java subprogram.oracore.java: import import import import java.

then you can include statements in the trigger body.executeUpdate (sql). the :NEW values are NULL. the old values are null. Because the row no longer exists after the row is deleted. For example: IF :NEW.toString() + ".CreateStatement().defaultConnection().. Statement stmt = conn.. The new column values are referenced using the NEW qualifier before the column name. COMM. String sql = "insert into logtab values ("+ old_id. and so on).Sal > 10000 . return. A trigger fired by a DELETE statement has meaningful access to :OLD column values only. CHAR old_name) Throws SQLException.close(). A trigger fired by an UPDATE statement has access to both old and new column values for both BEFORE and AFTER row triggers. Depending on the type of triggering statement. BEFORE DELETE'). certain correlation names might not have any meaning. '"+ old_ename.intValue() +".Sal < :OLD. For example. the PL/SQL code and SQL statements have access to the old and new column values of the current row affected by the triggering statement. stmt. and one for the new column value. while the old column values are referenced using the OLD qualifier before the column name.Sal . if the triggering statement is associated with the emp table (with the columns SAL. . IF :NEW. CoreException { Connection conn = JDBCConnection. However.public class thjvTriggers { public state void beforeDelete (NUMBER old_id. Because the row is being created by the INSERT. stmt.. you cannot modify :NEW values because ORA-4084 is raised if you try to modify :NEW values. } } Topics:      Accessing Column Values in Row Triggers Triggers on Object Tables Triggers and Handling Remote Exceptions Restrictions on Creating Triggers Who Uses the Trigger? Accessing Column Values in Row Triggers Within a trigger body of a row trigger.    A trigger fired by an INSERT statement has meaningful access to new column values only.. Two correlation names exist for every column of the table being modified: one for the old column value.

update tab1 set c1 = '<h1>Different Document Fragment</h1><p>Different text. or construct a new value using SUBSTR.Previously.put_line('Final value of CLOB column: '||:NEW.put_line('Old value of CLOB column: '||:OLD.. end. create table tab1 (c1 clob). :NEW. or DBMS_LOB calls for a BLOB. but not in an AFTER row trigger (because the triggering statement takes effect before an AFTER row trigger fires).'.c1). Correlation names can also be used in the Boolean expression of a WHEN clause. -. and calls to the DBMS_LOB package with BLOB columns: drop table tab1.. The parent row corresponding to this nested table element can be accessed using the parent qualifier. -. A NEW column value can be assigned in a BEFORE row trigger.c1 || to_clob('<hr><p>Standard footer paragraph. but a colon is not allowed when using the qualifiers in the WHEN clause or the REFERENCING option. If a BEFORE row trigger changes the value of NEW.Old and new values are available in both BEFORE and AFTER row triggers. select * from tab1. you couldn't change the new value for a LOB. INSTR. create or replace trigger trg1 before update on tab1 for each row begin dbms_output.Now.operations for a CLOB. the NEW and OLD qualifiers correspond to the new and old nested table elements. you can replace it.column. Example: Modifying LOB Columns with a Trigger You can treat LOB columns the same as other columns.'). -. Avoiding Trigger Name Conflicts (REFERENCING Option) . / set serveroutput on.c1).put_line('Proposed new value of CLOB column: '||:NEW.').c1 := :NEW. A colon (:) must precede the OLD and NEW qualifiers when they are used in a trigger body. INSTEAD OF Triggers on Nested Table View Columns In the case of INSTEAD OF triggers on nested table view columns.c1). dbms_output. dbms_output. insert into tab1 values ('<h1>HTML Document Fragment</h1><p>Some text. then an AFTER row trigger fired by the same statement sees the change assigned by the BEFORE row trigger. using regular SQL and PL/SQL functions with CLOB columns. The parent correlation name is meaningful and valid only inside a nested table trigger.

. Detecting the DML Operation that Fired a Trigger If more than one type of DML operation can fire a trigger (for example.. IF UPDATING ('SAL') THEN . assume that the table new was created as follows: CREATE TABLE new ( field1 NUMBER. field2 VARCHAR2(20)). the second condition evaluates to TRUE only if the statement that fired the trigger is an UPDATE statement. Because this is rare.. DELETING. you can execute blocks of code depending on the kind of DML operation that fired the trigger: IF INSERTING THEN . and it is then used in the trigger body. BEGIN . . END IF... and UPDATING to check which type of statement fire the trigger.Field2 := TO_CHAR (:newest.field1). this option is infrequently used. UPDATE OF Sal... For example. The following CREATE TRIGGER example shows a trigger defined on the new table that can use correlation names and avoid naming conflicts between the correlation names and the table name: CREATE OR REPLACE TRIGGER Print_salary_changes BEFORE UPDATE ON new REFERENCING new AS Newest FOR EACH ROW BEGIN :Newest. END IF. END. the trigger body can use the conditional predicates INSERTING. For example... . IF UPDATING THEN . In an UPDATE trigger. Within the code of the trigger body. assume a trigger is defined as the following: CREATE OR REPLACE TRIGGER . Notice that the NEW qualifier is renamed to newest using the REFERENCING option.. END IF..The REFERENCING option can be specified in a trigger body of a row trigger to avoid name conflicts among the correlation names and tables that might be named OLD or NEW. a column name can be specified with an UPDATING conditional predicate to determine if the named column is being updated. ON INSERT OR DELETE OR UPDATE OF emp).... Comm ON emp . The first condition evaluates to TRUE only if the statement that fired the trigger is an INSERT statement.

tbl_history. If the LOGON trigger raises an exception.1). the trigger can minimize its overhead when the column of interest is not being changed. a history table. are rolled back (unless the error is trapped by an exception handler). Only the trigger action is rolled back. If the system trigger is a DATABASE LOGON trigger and the user has ADMINISTER DATABASE TRIGGER privilege. A select from the history table to check that the trigger works is then shown at the end of the example: CREATE OR REPLACE TYPE t AS OBJECT (n NUMBER. Therefore. OBJECT_VALUE means the object as a whole. is also created in the following example. The trigger is a row-level trigger that executes once for each row affected by a DML statement. User-defined exceptions are commonly used in triggers that enforce complex security authorizations or constraints. Triggers on Object Tables You can use the OBJECT_VALUE pseudocolumn in a trigger on an object table because. while m is kept at 0.OBJECT_VALUE and :NEW. For SCHEMA LOGON triggers. Error Conditions and Exceptions in the Trigger Body If a predefined or user-defined error condition (exception) is raised during the execution of a trigger body.OBJECT_VALUE. if the user logging on is the trigger owner or has ALTER ANY TRIGGER privileges then logon is permitted. An update of the table tbl is done (each value of n is increased by 1). For tbl. You can also invoke a PL/SQL function with OBJECT_VALUE as the data type of an IN formal parameter. These old and new values are :OLD. m NUMBER) / CREATE TABLE tbl OF t / BEGIN .END. a trigger body can prevent the execution of the triggering statement by raising an exception. The code in the THEN clause runs only if the triggering UPDATE statement updates the SAL column. then the user is able to log on successfully even if the trigger raises an exception. Here is an example of the use of OBJECT_VALUE in a trigger. The trigger causes the old and new values of the object t in tbl to be written in tbl_history when tbl is updated. the values 1 through 5 are inserted into n. as of 10g Release 1 (10. then all effects of the trigger body. Only the trigger action is rolled back and an error is logged in the trace files and alert log. as well as the triggering statement. The error is logged in trace files and the alert log. This is one example of its use. To keep track of updates to values in an object table tbl. This way. logon fails except in the following cases:   Database startup and shutdown operations do not fail even if the system triggers for these events raise exceptions.

n = tbl. The output of the select is: 23-MAY-05 23-MAY-05 23-MAY-05 23-MAY-05 23-MAY-05 -----old: old: old: old: old: 1 2 3 4 5 0 0 0 0 0 -----new: new: new: new: new: 2 3 4 5 6 0 0 0 0 0 Triggers and Handling Remote Exceptions A trigger that accesses a remote site cannot do remote exception handling if the network link is unavailable. / The result of the select shows that all values of column n were increased by 1. EXCEPTION WHEN OTHERS THEN INSERT INTO Emp_log VALUES ('x').new: '||j. / ------------------------------------------------------------------------------UPDATE tbl SET tbl.n+1 / BEGIN FOR j IN (SELECT d.. .Put_Line ( j.5 LOOP INSERT INTO tbl VALUES (t(j.OBJECT_VALUE. new_obj) VALUES (SYSDATE. END LOOP. For example: CREATE OR REPLACE TRIGGER Example AFTER INSERT ON emp FOR EACH ROW BEGIN When dblink is inaccessible. old_obj t. old_obj. 0)).FOR j IN 1.OBJECT_VALUE). new_obj t) / CREATE OR REPLACE TRIGGER Tbl_Trg AFTER UPDATE ON tbl FOR EACH ROW BEGIN INSERT INTO tbl_history (d. :NEW.new_obj. old_obj.d|| ' -.m).old_obj.old: '||j.n||' '||j. END. END. The value of m remains 0.n||' '||j.old_obj.new_obj. :OLD. new_obj FROM tbl_history) LOOP Dbms_Output. compilation fails here: INSERT INTO emp@Remote VALUES ('x'). END LOOP. END Tbl_Trg. END.m|| ' -. / CREATE TABLE tbl_history ( d DATE.

CREATE OR REPLACE PROCEDURE Insert_row_proc AS BEGIN INSERT INTO emp@Remote VALUES ('x'). when the remote INSERT statement fails because the link is down. because the trigger does not complete compilation. thus. SELECT statements in cursor definitions. SQL Statements Allowed in Trigger Bodies A trigger body can contain SELECT INTO statements. if a remote site is unavailable when the trigger must compile.A trigger is compiled when it is created. The previous example exception statement cannot run. Restrictions on Creating Triggers Coding triggers requires some restrictions that are not required for standard PL/SQL blocks. END. Topics:        Maximum Trigger Size SQL Statements Allowed in Trigger Bodies Trigger Restrictions on LONG and LONG RAW Data Types Trigger Restrictions on Mutating Tables Restrictions on Mutating Tables Relaxed System Trigger Restrictions Foreign Function Callouts Maximum Trigger Size The size of a trigger cannot be more than 32K. the work-around for the previous example is as follows: CREATE OR REPLACE TRIGGER Example AFTER INSERT ON emp FOR EACH ROW BEGIN Insert_row_proc. then the database cannot validate the statement accessing the remote database. EXCEPTION WHEN OTHERS THEN INSERT INTO Emp_log VALUES ('x'). END. which already has a validated statement for accessing the remote database. and the compilation fails. Because stored subprograms are stored in a compiled form. Thus. . the exception is caught. and all other DML statements. The trigger in this example compiles successfully and invokes the stored subprogram.

If a timestamp or signature mismatch is found during execution of the trigger. and the trigger is invalidated. DROP TABLE and ALTER COMPILE. the effects of the trigger body and triggering statement are rolled back. because the subprogram runs within the context of the trigger body. a run-time error occurs. Trigger Restrictions on LONG and LONG RAW Data Types LONG   and LONG RAW data types in triggers are subject to the following restrictions: A SQL statement within a trigger can insert data into a column of LONG or LONG RAW data type. or INSERT statement.   Trigger Restrictions on Mutating Tables A mutating table is a table that is being modified by an UPDATE. see Using Compound Triggers to Avoid Mutating-Table Error. If data from a LONG or LONG RAW column can be converted to a constrained data type (such as CHAR and VARCHAR2). :NEW and :PARENT cannot be used with LONG or LONG RAW columns.A system trigger body can contain the DDL statements CREATETABLE. This restriction prevents a trigger from seeing an inconsistent set of data. or a table that might be updated by the effects of a DELETE CASCADE constraint. The maximum length for these data types is 32000 bytes. (You can use compound triggers to avoid the mutating-table error. However. Statements inside a trigger can reference remote schema objects. The session that issued the triggering statement cannot query or modify a mutating table. pay special attention when invoking remote subprograms from within a local trigger. then the remote subprogram is not run. then a LONG or LONG RAW column can be referenced in a SQL statement within a trigger. Note: A subprogram invoked by a trigger cannot run the previous transaction control statements. This restriction applies to all triggers that use the FOR EACH ROW clause. DELETE. Variables cannot be declared using the LONG or LONG RAW data types. and control is returned to the user or application. When a trigger encounters a mutating table. A nonsystem trigger body cannot contain DDL or transaction control statements.) Consider the following trigger: CREATE OR REPLACE TRIGGER Emp_count AFTER DELETE ON emp . ALTERTABLE. For more information. Views being modified in INSTEAD OF triggers are not considered mutating.

If the following SQL statement is entered: DELETE FROM emp WHERE empno = 7499. A loop-back database link makes a local table appear remote by defining an Oracle Net path back to the database that contains the link. you might use two triggers—an AFTER row trigger that updates a temporary table.PUT_LINE('There are now ' || n || ' employees. BEGIN SELECT COUNT(*) INTO n FROM emp. Declarative constraints are checked at various times with respect to row triggers. and maintaining a count of . you can bypass these restrictions by using a temporary table. Restrictions on Mutating Tables Relaxed The mutating error described in Trigger Restrictions on Mutating Tables prevents the trigger from reading or modifying the table that the parent statement is modifying. update set default.'). END.emp is mutating. Update cascade. For example. as of Oracle Database Release 8. update set null. providing the constraint is not self-referential. you can create triggers (just not row triggers) to read and modify the parent and child tables. DBMS_OUTPUT. and the trigger. in place of a single AFTER row trigger that updates the original table.1. a PL/SQL table.FOR EACH ROW DECLARE n INTEGER. and an AFTER statement trigger that updates the original table with the values from the temporary table. See Also: Oracle Database Concepts for information about the interaction of triggers and constraints Because declarative referential constraints are not supported between tables on different nodes of a distributed database. a deletion from the parent table causes BEFORE and AFTER triggers to fire once. An error is returned because the table is mutating when the row is deleted: ORA-04091: table HR. the mutating table restrictions do not apply to triggers that access remote nodes. If you must update a mutating table. These restrictions are also not enforced among tables in the same database that are connected by loop-back database links. Therefore. or a package variable. it becomes a statement trigger that is not subject to this restriction. resulting in a mutating table error. trigger/function might not see it If you delete the line "FOR EACH ROW" from the trigger. This allows most foreign key constraint actions to be implemented through their obvious afterrow trigger. However. delete set default. inserting a missing parent.

the statement updates (3) to (4) in p. END. if table p has three rows with the values (1). because the foreign key constraint guarantees that no matching foreign key rows are locked before the after-row trigger is invoked. (3). or track updates to foreign key values and modify the trigger to ensure that no row is updated twice. For example.p1 WHERE f1 = :OLD. For example. and table f also has three rows with the values (1). different event attribute functions are available. pt AFTER UPDATE ON p FOR EACH ROW BEGIN f1 = :NEW. then the trigger itself does not fire after the creation. either forbid multiple-row updates to p that change the primary key and reuse existing primary key values. The trigger cannot miss rows that were changed but not committed by another transaction. and the trigger updates (1) to (2) in f. then the following statement updates p correctly but causes problems when the trigger updates f: UPDATE p SET p1 = p1+1. and the trigger updates both rows of value (2) to (3) in f. if you execute the following SQL statement: CREATE OR REPLACE TRIGGER my_trigger AFTER CREATE ON DATABASE BEGIN null.children can all be implemented easily. The statement first updates (1) to (2) in p. For example. if you create a trigger that fires after all CREATE events. The relationship of the data in p and f is lost. To avoid this problem. (2). That is the only problem with this technique for foreign key updates. . Only committed triggers fire. / (p1 NUMBER CONSTRAINT pk_p_p1 PRIMARY KEY). and the trigger updates all three rows in f from (3) to (4). Finally. (2). this is an implementation of update cascade: CREATE TABLE p CREATE TABLE f CREATE TRIGGER UPDATE f SET END. (3).p1. For example. certain DDL operations might not be allowed on DDL events. For example. because the correct information about this trigger was not committed at the time when the trigger on CREATE events fired. Check Event Attribute Functions before using an event attribute function. leaving two rows of value (2) in f. This implementation requires care for multiple-row updates. System Trigger Restrictions Depending on the event. (f1 NUMBER CONSTRAINT fk_f_f1 REFERENCES p). because its effects might be undefined rather than producing an error condition. Then the statement updates (2) to (3) in p.

An anonymous block is compiled each time it is loaded into memory. Code generation A trigger is fully compiled when the CREATE TRIGGER statement executes. To see trigger compilation errors. and a parse tree is generated. If an error occurs during the compilation of a trigger. The trigger code is stored in the data dictionary. Topics:   Dependencies for Triggers Recompiling Triggers Dependencies for Triggers Compiled triggers have dependencies. and its compilation has three stages: 1. it is unnecessary to open a shared cursor in order to execute the trigger. returns the owner of the trigger. They become invalid if a depended-on object. is modified. Who Uses the Trigger? The following statement. Compiling Triggers An important difference between triggers and PL/SQL anonymous blocks is their compilation. such as a stored subprogram invoked from the trigger body. 3. Semantic checking: Type checking and further processing on the parse tree. trigger my_trigger does not fire after the creation of my_trigger. 2. Foreign Function Callouts All restrictions on foreign function callouts also apply. the DML statement fails (unless the trigger was created in the disabled state). Therefore. the trigger is still created. Therefore.Then. Syntax checking: PL/SQL syntax is checked. either use the SHOW ERRORS statement in SQL*Plus or Enterprise Manager. if a DML statement fires the trigger. or SELECT the errors from the USER_ERRORS view. the trigger executes directly. The database does not fire a trigger that is not committed. Triggers that are invalidated for dependency reasons are recompiled when next invoked. inside a trigger. not the name of user who is updating the table: SELECT Username FROM USER_USERS. .

the following statement recompiles the PRINT_SALARY_CHANGES trigger: ALTER TRIGGER Print_salary_changes COMPILE. There are also exceptions for SHUTDOWN events and for LOGON events if you login as SYSTEM. see Oracle Database Concepts. An attempt is made to validate the trigger on occurrence of the event. REFERENCED_OWNER. For more information about dependencies between schema objects. you must include the OR REPLACE option in the CREATE TRIGGER statement. For example. REFERENCED_TYPE FROM ALL_DEPENDENCIES WHERE OWNER = 'HR' and TYPE = 'TRIGGER'. dependency between triggers and queues cannot be maintained. The OR REPLACE option is provided to allow a new version of an existing trigger to replace the older version. you must own the trigger or have the ALTER ANY TRIGGER system privilege. Note:   There is an exception for STARTUP events: STARTUP events succeed even if the trigger fails. the following statement shows the dependencies for the triggers in the HR schema: SELECT NAME. . without affecting any grants made for the original version of the trigger. If the function or package specified in the trigger is dropped. To recompile a trigger.You can examine the ALL_DEPENDENCIES view to see the dependencies for a trigger. a trigger cannot be explicitly altered: It must be replaced with a new definition. Modifying Triggers Like a stored subprogram. or disable a trigger.) When replacing a trigger. If the trigger cannot be validated successfully. the trigger can be dropped using the DROP TRIGGER statement. Recompiling Triggers Use the ALTER TRIGGER statement to recompile a trigger manually. and the event fails. Alternatively. or you must have the DROP ANY TRIGGER system privilege. and you can rerun the CREATE TRIGGER statement. the trigger must be in your schema. (The ALTER TRIGGER statement is used only to recompile. REFERENCED_NAME. enable. For example. then it is marked VALID WITH ERRORS. To drop a trigger. Because the DBMS_AQ package is used to enqueue a message. then the trigger is marked invalid. Triggers might depend on other functions or packages.

table. To enable all triggers defined for a specific table. to disable the trigger named Reorder. SCHEMA.Debugging Triggers You can debug a trigger using the same facilities available for stored subprograms. . to enable all triggers defined for the Inventory table. Viewing Information About Triggers The *_TRIGGERS static data dictionary views reveal information about triggers. enter the following statement: ALTER TRIGGER Reorder ENABLE. To disable a trigger. enter the following statement: ALTER TABLE Inventory DISABLE ALL TRIGGERS. You must perform a large data load. For example. Enabling Triggers To enable a disabled trigger. use the ALTER TABLE statement with the ENABLE clause and the ALL TRIGGERS option. Disabling Triggers You might temporarily disable a trigger if:    An object it references is not available. use the ALTER TRIGGER statement with the ENABLE clause. For example. You are reloading data. The column TABLE_NAME is null if the base object is not table or view. to enable the disabled trigger named Reorder. To disable all triggers defined for a specific table. or view. use the ALTER TABLE statement with the DISABLE clause and the ALL TRIGGERS option. use the ALTER TRIGGER statement with the DISABLE option. enter the following statement: ALTER TABLE Inventory ENABLE ALL TRIGGERS. See Oracle Database Advanced Application Developer's Guide. For example. For example. to disable all triggers defined for the Inventory table. The column BASE_OBJECT_TYPE specifies whether the trigger is based on DATABASE. enter the following statement: ALTER TRIGGER Reorder DISABLE. and you want it to proceed quickly without firing triggers.

BEGIN . IF x = 0 THEN INSERT INTO Pending_orders VALUES (:NEW.The column ACTION_TYPE specifies whether the trigger is a call type trigger or a PL/SQL trigger. sysdate). TYPE TRIGGERING_STATEMENT TABLE_NAME ---------------. :NEW.Reorder_quantity. AFTER_ROW. See Also: Oracle Database Reference for information about *_TRIGGERS static data dictionary views For example. BEGIN SELECT COUNT(*) INTO x FROM Pending_orders WHERE Part_no = :NEW. END IF. AFTER_STATEMENT. BEFORE EVENT.Part_no.-----------AFTER EACH ROW UPDATE INVENTORY SELECT Trigger_body FROM USER_TRIGGERS WHERE Trigger_name = 'REORDER'. The following two queries return information about the REORDER trigger: SELECT Trigger_type. or AFTER EVENT (the last two apply only to database events). and INSTEAD_OF_ROW has the value YES or NO. The column TRIGGERING_EVENT includes all system and DML events. assume the following statement was used to create the Reorder trigger: CREATE OR REPLACE TRIGGER Reorder AFTER UPDATE OF Parts_on_hand ON Inventory FOR EACH ROW WHEN(NEW.Part_no.Reorder_point) DECLARE x NUMBER. END. The column TRIGGER_TYPE specifies the type of the trigger. TRIGGER_BODY -------------------------------------------DECLARE x NUMBER. Table_name FROM USER_TRIGGERS WHERE Trigger_name = 'REORDER'. BEFORE_ROW.-------------------------.Parts_on_hand < NEW. Each of the columns BEFORE_STATEMENT. for example COMPOUND. Triggering_event.

Table 9-2 Comparison of Built-in Auditing and Trigger-Based Auditing Audit Feature Description . END. triggers are commonly used to:          Provide sophisticated auditing Prevent invalid transactions Enforce referential integrity (either those actions not supported by declarative constraints or across nodes in a distributed database) Enforce complex business rules Enforce complex security authorizations Provide transparent event logging Automatically generate derived column values Enable building complex views that are updatable Track database events This section provides an example of each of these trigger applications. :NEW. These examples are not meant to be used exactly as written: They are provided to assist you in designing your own triggers.SELECT COUNT(*) INTO x FROM Pending_orders WHERE Part_no = :NEW. compared to auditing defined by triggers. END IF. while triggers can provide financial audit facility. For example. sysdate). Auditing with Triggers Triggers are commonly used to supplement the built-in auditing features of the database. the AUDIT statement is considered a security audit facility. Examples of Trigger Applications You can use triggers in a number of ways to customize information management in the database. as shown in Table 9-2. use triggers to provide value-based auditing for each row. use triggers only when more detailed audit information is required.Reorder_quantity. Sometimes.Part_no.Part_no. For example. When deciding whether to create a trigger to audit database activity. consider what the database's auditing features provide. Although triggers can be written to record information similar to that recorded by the AUDIT statement. IF x = 0 THEN INSERT INTO Pending_orders VALUES (:NEW.

and less prone to errors. Auditing of Unsuccessful Data Access Sessions can be Audited When using triggers to provide sophisticated auditing. If no records are found. Session and Execution time Auditing Using the database auditing features. Triggers cannot audit by session. For more information about autonomous transactions. then the AFTER trigger does not fire. For example. This shows how triggers can be used to provide value-based auditing and how to use public package variables. and so on). when compared to auditing functions defined by triggers. Triggers can also require the user to supply a "reason code" for issuing the audited SQL statement. Comparatively. Declarative Method Auditing features enabled using the standard database features are easier to declare and maintain. The following example demonstrates a trigger that audits modifications to the emp table for each row. any audit information generated by a trigger is rolled back if the triggering statement is rolled back. Auditing Options Any changes to existing auditing options can also be audited to guard against can be Audited malicious database activity. deadlocks. Connections and disconnections. It requires that a "reason code" be stored in a global package variable before the update. and audit processing is not carried out unnecessarily. triggers permit auditing of DML statements entered against tables. Centralized Audit All database audit information is recorded centrally and automatically using Trail the auditing features of the database. can be recorded using standard database auditing. which can be useful in both row and statement-level auditing situations. logical I/Os. However. Note: . records can be generated once every time an audited statement is entered (BY ACCESS) or once for every session that enters an audited statement (BY SESSION). see Oracle Database Concepts. and DDL auditing at SCHEMA or DATABASE level. Database auditing can be set to audit when unsuccessful data access occurs. an audit record is generated each time a trigger-audited table is referenced. unless autonomous transactions are used. The triggering statement is subjected to any applicable constraints. Choosing between AFTER row and AFTER statement triggers depends on the information being audited. as well as session activity (physical I/Os. row triggers provide value-based auditing for each table row. AFTER triggers are normally used.Audit Feature DML and DDL Auditing Description Standard auditing options permit auditing of DML and DDL statements regarding all types of schema objects and structures.

CREATE TABLE Audit_employee ( Oldssn NUMBER. new row is inserted into predefined auditing table named AUDIT_EMPLOYEE containing existing & new values of the emp table & reason code defined by REASON variable of AUDITPACKAGE. Bonus NUMBER. Sal NUMBER(7. Oldjob VARCHAR2(2). Oldname VARCHAR2(10). Newjob VARCHAR2(2). Comm NUMBER(7. /* If preceding condition evaluates to TRUE.Reason IS NULL THEN Raise_application_error(-20201. REASON can be set by the application by a statement such as EXECUTE AUDITPACKAGE.SET_REASON(Reason_string)'). & effects of triggering statement are rolled back. CREATE OR REPLACE TRIGGER Audit_employee AFTER INSERT OR DELETE OR UPDATE ON Emp99 FOR EACH ROW BEGIN /* AUDITPACKAGE is a package with a public package variable REASON. Newname VARCHAR2(10). Job VARCHAR2(9). user-specified error number & message is raised. END. PROCEDURE Set_reason(Reason VARCHAR2). Otherwise.2). Newsal NUMBER. Deptno NUMBER(2). Oldsal NUMBER. Systemdate DATE). CREATE TABLE Emp99 ( Empno NOT NULL NUMBER(4). trigger stops execution. Newssn NUMBER. Ssn NUMBER. END IF. Mgr NUMBER(4). Hiredate DATE.SET_REASON(reason_string). 'Must specify reason' || ' with AUDITPACKAGE. "Old" values are NULL if triggering statement is INSERT . */ IF Auditpackage.2).You might need to set up the following data structures for the examples to work: CREATE OR REPLACE PACKAGE Auditpackage AS Reason VARCHAR2(10). User1 VARCHAR2(10). A package variable has state for the duration of a session and that each session has a separate copy of all package variables. Job_classification NUMBER). Ename VARCHAR2(10). Reason VARCHAR2(10).

:OLD. :NEW. */ INSERT INTO Audit_employee VALUES ( :OLD.Ename. :OLD. :NEW.Job_classification. auditpackage.Reason.Ssn.& "new" values are NULL if triggering statement is DELETE.Sal.Sal. Sysdate ). END. User. :NEW. :OLD. The following simple AFTER statement trigger sets the reason code back to NUL . :NEW.Ssn.Ename. Optionally. you can also set the reason code back to NULL if you wanted to force the reason code to be set for every update.Job_classification.

Sign up to vote on this title
UsefulNot useful