murach’s oracle sql and pl/sql, c16© 2014, mike murach & associates, inc.slide 1 thursday,...
TRANSCRIPT
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 1
Thursday, March 12, 12:30 – 13:30PM.
MIDTERM
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 2
Triggers Chapter 16
Triggers• A trigger is a statement that is executed
automatically by the system as a side effect of a modification to the database.
• To design a trigger mechanism, we must:
– Specify the conditions under which the trigger is to be executed.
– Specify the actions to be taken when the trigger executes.
• Introduced to SQL standard in SQL:1999,
• Supported even earlier using non-standard syntax by most DBMSes.
– Syntax illustrated here is for Oracle 11g.
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 4
Objectives
Applied
Create triggers that fire before or after an INSERT, UPDATE, or DELETE statement is executed for a table.
Create triggers that can be used to make views updatable.
Create triggers that fire when DDL events occur.
Create compound triggers.
Use Oracle SQL Developer to work with triggers.
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 5
Objectives (continued)
Knowledge
Distinguish between a statement-level trigger and a row-level trigger.
Describe how a trigger can be used to: enforce data consistency, work with sequences, or make a view updatable.
Describe the operation of a compound trigger.
Describe the mutating-table error.
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 6
The syntax of the CREATE TRIGGER statement for a table
CREATE [OR REPLACE] TRIGGER trigger_name {BEFORE|AFTER} {DELETE|INSERT|UPDATE [OF col_name1 [, col_name2]...]} [OR {DELETE|INSERT|UPDATE [OF col_name1 [, col_name2]...]}]... ON table_name [FOR EACH ROW [WHEN (trigger_condition)]] pl_sql_block
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 7
A trigger that corrects mixed-case state names CREATE OR REPLACE TRIGGER vendors_before_update_state BEFORE INSERT OR UPDATE OF vendor_state ON vendors FOR EACH ROW WHEN (NEW.vendor_state != UPPER(NEW.vendor_state)) BEGIN :NEW.vendor_state := UPPER(:NEW.vendor_state); END; /
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 8
An UPDATE statement that fires the trigger UPDATE vendors SET vendor_state = 'wi' WHERE vendor_id = 1;
A SELECT statement that shows the new row SELECT vendor_name, vendor_state FROM vendors WHERE vendor_id = 1;
The result set
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 9
A trigger that validates line item amounts CREATE OR REPLACE TRIGGER invoices_before_update_total BEFORE UPDATE OF invoice_total ON invoices FOR EACH ROW DECLARE sum_line_item_amount NUMBER; BEGIN SELECT SUM(line_item_amt) INTO sum_line_item_amount FROM invoice_line_items WHERE invoice_id = :new.invoice_id; IF sum_line_item_amount != :new.invoice_total THEN RAISE_APPLICATION_ERROR(-20001, 'Line item total must match invoice total.'); END IF; END; /
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 10
An UPDATE statement that fires the trigger UPDATE invoices SET invoice_total = 600 WHERE invoice_id = 100;
The response from the system ORA-20001: Line item total must match invoice total.
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 13
Triggers are commonly used to monitor events occurring in a database.
AFTER Triggers
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 14
A statement that creates an audit table CREATE TABLE invoices_audit ( vendor_id NUMBER NOT NULL, invoice_number VARCHAR2(50) NOT NULL, invoice_total NUMBER NOT NULL, action_type VARCHAR2(50) NOT NULL, action_date DATE NOT NULL );
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 15
An AFTER trigger that inserts rows into the table CREATE OR REPLACE TRIGGER invoices_after_dml AFTER INSERT OR UPDATE OR DELETE ON invoices FOR EACH ROW BEGIN IF INSERTING THEN INSERT INTO invoices_audit VALUES (:new.vendor_id, :new.invoice_number, :new.invoice_total, 'INSERTED', SYSDATE); ELSIF UPDATING THEN INSERT INTO invoices_audit VALUES (:old.vendor_id, :old.invoice_number, :old.invoice_total, 'UPDATED', SYSDATE); ELSIF DELETING THEN INSERT INTO invoices_audit VALUES (:old.vendor_id, :old.invoice_number, :old.invoice_total, 'DELETED', SYSDATE); END IF; END; /
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 16
An INSERT statement that fires the trigger INSERT INTO invoices VALUES (115, 34, 'ZXA-080', '30-AUG-14', 14092.59, 0, 0, 3, '30-SEP-14', NULL);
A DELETE statement that fires the trigger DELETE FROM invoices WHERE invoice_number = 'ZXA-080';
A statement that retrieves the audit table rows SELECT * FROM invoices_deleted;
The result set
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 17
Triggers for Views
Recall updateable views?
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 18
The syntax of the CREATE TRIGGER statement for a view
CREATE [OR REPLACE] TRIGGER trigger_name INSTEAD OF {DELETE|INSERT|UPDATE [OF col_name1 [, ] col_name2...]} [OR {DELETE|INSERT|UPDATE [OF col_name1 [, ] col_name2...]}]... ON view_name [FOR EACH ROW [WHEN (trigger_condition)]] pl_sql_block
A statement that creates a view CREATE OR REPLACE VIEW ibm_invoices AS SELECT invoice_number, invoice_date, invoice_total FROM invoices WHERE vendor_id = 34;
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 19
An INSTEAD OF INSERT trigger for a view CREATE OR REPLACE TRIGGER ibm_invoices_instead_of_insert INSTEAD OF INSERT ON ibm_invoices BEGIN INSERT INTO invoices VALUES (invoice_id_seq.NEXTVAL, 34, :new.invoice_number, :new.invoice_date, :new.invoice_total, 0, 0, 3, :new.invoice_date + 30, NULL); END; /
An statement that succeeds due to the trigger INSERT INTO ibm_invoices VALUES ('ZXA-080', '30-AUG-14', 14092.59);
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 20
A statement that retrieves the rows from the view SELECT * FROM ibm_invoices;
The result set
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 21
Triggers on DDL Statements
What’s a DDL statement?
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 22
The syntax of the CREATE TRIGGER statement for a DDL statement
CREATE [OR REPLACE] TRIGGER trigger_name {BEFORE|AFTER} ddl_event [OR ddl_event]... ON {[schema_name.]SCHEMA|DATABASE} pl_sql_block
DDL events CREATE
ALTER
DROP
GRANT
REVOKE
DDL
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 23
A trigger that works with DDL statements CREATE OR REPLACE TRIGGER ap_before_create_drop BEFORE CREATE OR DROP ON ap.SCHEMA BEGIN RAISE_APPLICATION_ERROR(-20001, 'You cannot create or drop an object in the AP schema'); END; /
A CREATE TABLE statement that fires the trigger CREATE TABLE ap.test1 (test_id NUMBER);
The response from the system ORA-20001: You cannot create or drop an object in the AP schema
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 24
Disable/Enable Triggers
Why would I want to disable a trigger?
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 25
Statements that disable and enable a trigger ALTER TRIGGER ap_before_create DISABLE; CREATE TABLE test1 (test_id NUMBER); DROP TABLE test1; ALTER TRIGGER ap_before_create ENABLE;
Statements that disable and enable all triggers ALTER TABLE invoices DISABLE ALL TRIGGERS; ALTER TABLE invoices ENABLE ALL TRIGGERS;
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 26
A statement that renames a trigger ALTER TRIGGER invoices_before_update_total RENAME TO invoices_before_update_inv_tot;
A statement that drops a trigger DROP TRIGGER ap_before_create;
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 27
Compound Triggers
Version note Compound triggers were introduced with Oracle Database 11g and
are not available to earlier versions of Oracle Database.
Why do we need another type of trigger?•It solves an well-known problem in Oracle.•Contains code that executes:
• BEFORE the triggering statement executes.• BEFORE the row is modified.• AFTER the row is modified.• AFTER the triggering statement has finished.
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 28
A compound trigger CREATE OR REPLACE TRIGGER invoices_compound_update FOR UPDATE OF invoice_total, credit_total ON invoices COMPOUND TRIGGER test_value NUMBER := 1; BEFORE STATEMENT IS BEGIN DBMS_OUTPUT.PUT_LINE('before statement: ' || test_value); END BEFORE STATEMENT; BEFORE EACH ROW IS BEGIN DBMS_OUTPUT.PUT_LINE('before row: ' || test_value); END BEFORE EACH ROW;
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 29
A compound trigger (continued) AFTER EACH ROW IS BEGIN DBMS_OUTPUT.PUT_LINE('after row: ' || test_value); END AFTER EACH ROW; AFTER STATEMENT IS BEGIN DBMS_OUTPUT.PUT_LINE('after statement: ' || test_value); END AFTER STATEMENT; END; /
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 30
A script that fires the trigger SET SERVEROUTPUT ON; UPDATE invoices SET credit_total = 0 WHERE invoice_id = 100;
The response from the system before statement: 1 before row: 1 after row: 1 after statement: 1
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 37
A trigger in SQL Developer
Murach’s Oracle SQL and PL/SQL, C16 © 2014, Mike Murach & Associates, Inc. Slide 38
A trigger in the Edit window