14 Triggers / Embedded SQL COMS20700 Databases Dr. Essam Ghadafi
TRIGGERS A trigger is a procedure that is executed automatically whenever a specific event occurs. You can use triggers to enforce constraints and do other stuff.
TRIGGERS Syntax: CREATE [OR REPLACE] TRIGGER <trigger_name> {BEFORE AFTER} {INSERT DELETE UPDATE} ON <table_name> [REFERENCING [NEW AS <new_name>] [OLD AS <old_name>]] [FOR EACH ROW [WHEN (<trigger_condition>)]] [ Declare /* Declaration Section */ ] BEGIN /* Trigger Body */ END [<trigger_name>];
TYPES OF EVENTS DML statements: INSERT, UPDATE, DELETE on a particular table or view. DDL statements: CREATE, ALTER, DROP. Database events: e.g., LOG ON, LOG OFF, STARTUP, SHUTDOWN,...
TRIGGERS Trigger Event - The triggering SQL statement: INSERT UPDATE DELETE Timing - When the trigger is fired: BEFORE Fires before the triggering SQL statement is executed. AFTER Fires after the triggering SQL statement is executed. Level: STATEMENT Executes once for each transaction (Default). ROW Executes once for each row in a transaction.
NEW AND OLD OLD.<attribute name> The value of the attribute before a change from an UPDATE statement or before a DELETE statement. This value is NULL for INSERT statements. NEW.<attribute name> The value of the attribute after an UPDATE/INSERT statement. This value is NULL for DELETE statements. Can be aliased NEW AS newname OLD AS oldname Note: Those are preceded by a colon in the body but not in the WHEN clause.
TRIGGER EXAMPLES Example1: Trigger salarycheck enforces a check constraint. CREATE TRIGGER salarycheck AFTER INSERT OR UPDATE OF salary ON Employee FOR EACH ROW BEGIN IF (:new.salary < 0) THEN RAISE_APPLICATION_ERROR(-20000, salary is < 0 ); END IF; END salarycheck; /
TRIGGERS EXAMPLES Example2: Trigger addhigh inserts records into HighIncome table whenever they are added to the Employee table with a salary > 3000. CREATE TRIGGER addhigh AFTER INSERT ON Employee REFERENCING NEW AS newrow FOR EACH ROW WHEN (newrow.salary >3000) BEGIN INSERT INTO HighIncome VALUES(:newRow.name, :newrow.salary); END addhigh;
EXECUTION MODEL Execute all BEFORE statement triggers that apply. Loop for each row affected by the SQL statement Execute all BEFORE row triggers that apply. Change the row. Perform integrity constraint checking. Execute all AFTER row triggers that apply. Complete integrity constraint checking. Execute all AFTER statement triggers that apply.
MULTIPLE TRIGGER EVENTS How to tell which statement fired the trigger? Use the flags: INSERTING, UPDATING and DELETING. IF INSERTING THEN... ELSIF UPDATING THEN... ELSIF Deleting THEN... ELSE... END IF;
TRIGGERS Displaying Trigger Definition Errors If you get a message Warning: "Trigger created with compilation errors.". You can see the error messages by typing: SHOW ERRORS TRIGGER <trigger_name>; Alternatively, check the User_Errors table...
TRIGGERS Listing Your Defined Triggers To view a list of all your defined triggers, see table User_Triggers Deleting a Trigger DROP TRIGGER <trigger_name>; Temporarily Disabling a Trigger ALTER TRIGGER <trigger_name> DISABLE; To re-enable the trigger: ALTER TRIGGER <trigger_name> ENABLE;
TRIGGERS Disabling/Enabling all Triggers on a Table ALTER TABLE <table_name> ENABLE ALL TRIGGERS; ALTER TABLE <table_name> DISABLE ALL TRIGGERS; Note: When you drop a table, all triggers on that table will be deleted automatically. To create a TRIGGER, you must have either of the privileges: CREATE TRIGGER CREATE ANY TRIGGER
FINAL EXAMPLE Keeping a log of all deletions from table Employee. Suppose that many users are authorized to delete from the table. GRANT DELETE ON <table_name> TO <user_name>; CREATE TABLE EmpDelLog ( username VARCHAR2(10), deletion_time DATE, empno Number ); We write the trigger: CREATE TRIGGER empdelete BEFORE DELETE ON Employee FOR EACH ROW BEGIN INSERT INTO EmpDelLog VALUES(USER, SYSDATE, :OLD.empno); END empdelete;
MUTATING TABLES You get a mutating table error if you try to modify or read from the table associated with the trigger within a row-level trigger, i.e. trying to access rows that are currently in the state of change. Solution: If you have to access the table associated with the trigger withing the trigger, define the trigger as a statement-level trigger not a row-level trigger.
MUTATING TABLES Example: CREATE OR REPLACE TRIGGER Employee_Check AFTER INSERT ON Employee For each row Declare sal Employee.salary%TYPE; BEGIN SELECT salary INTO sal FROM Employee WHERE empno=9041; END Employee_Check; / INSERT INTO Employee values (10203, Paul Ryan, 2450); You will get the following Error: Error: ORA-04091: table UserName.Employee is mutating, trigger/function may not see it
EMBEDDED SQL (OVERVIEW) Combines the powerful capabilities of a high-level language (C/C++,.Net, COBOL, Java,... etc.) with the database manipulation capabilities of SQL. SQL statements can be executed from any application program. Oracle has an environment called Pro*C/C++ which one can use to write C/C++ programs that incorporate SQL statements. The precompiler first replaces the SQL code in the program with C/C++ code. The whole C/C++ program is then compiled by the language compiler.
EMBEDDED SQL Pro*C Communication between the program and the database is via host variables. All SQL statements start with EXEC SQL and end with a semicolon. Example: int ageval; int empnoval; printf("enter the Employee Number:"); scanf("%d",&empnoval); EXEC SQL SELECT age INTO :ageval FROM Employee WHERE empno=:empnoval; printf("the age is %d\n", ageval);
DYNAMIC SQL If you use fixed SQL statements, then you need to recompile the program every time you need to change them... Dynamic SQL allows executing dynamically generated SQL statements. For dynamic SQL, we need: 1 PREPARE: To convert a string into a SQL statement. 2 EXECUTE: To execute the SQL statement.
DYNAMIC SQL Example-1: char *s = "INSERT INTO Emp VALUES(567, Chris, 3400)"; EXEC SQL PREPARE query FROM :s; EXEC SQL EXECUTE query; Alternatively, one can combine PREPARE and EXECUTE using EXECUTE IMMEDIATE. Example-2: char *s = "INSERT INTO Emp VALUES(567, Chris, 3400)"; EXEC SQL EXECUTE IMMEDIATE :s;