You are on page 1of 32

Chap.

14

14

Database Trigger
Trigger PL/SQL Block stored
subprogram ( procedure, function
package)

DDL


DML
INSERT, UPDATE DELETE

Database
startup shutdown logon logoff
Triggering
Event
trigger
referential integrity

trigger
trigger body trigger
(transparent)
trigger
DML DDL
trigger referential integrity

.

Chap. 14

referential integrity
Database triggers

database triggers
DDL DML
(auditing)

data-integrity relationships


system event
trigger
ALTER TABLE

ALTER ALTER
ANY TABLE
(system privilege) CREATE TRIGGER (
role RESOURCE)
trigger trigger
ALTER ANY TRIGGER
Trigger 2 Database Trigger
Application Trigger
Database Trigger Trigger
INSERT, UPDATE
DELETE (triggering statement)

Database Trigger
View

.

Chap. 14

DML
view trigger base table view
( Database
Trigger )
Application Trigger Trigger

Trigger

Oracle Form Builder

database trigger
trigger

Database Trigger
centralized Global operations
triggers
trigger Oracle trigger
integrity
constraints Oracle
trigger

trigger

14.1

Database Trigger (
trigger)

database trigger

audit

Chap. 14

A P P L IC A T I O N
S Q L > IN S E R T IN T O E M P ...,

EMP table
EMPNOENAME JOB
SAL
C H E C K _ S A L _ trig g e r
7838
KING PRESIDENT 5000
7698
BLAKE MANAGER 2850
7369
SMITH CLERK
800
7788
SCOTT ANALYST 3000

trigger
trigger trigger timing, triggering event, trigger
type trigger body
- Trigger timing trigger
(fired)

BEFORE AFTER
trigger
(events) trigger
trigger
logon
- Triggering event data
manipulation trigger
INSERT,
UPDATE DELETE
- Trigger type
trigger body statement
row
- Trigger body
trigger PL/SQL Block

14.1.1 Trigger timing


trigger (fired)
(database transaction)

.

Chap. 14

- BEFORE Trigger

Trigger
trigger
event
event INSERT
UPDATE
- AFTER Trigger
Trigger
trigger
event
BEFORE trigger
- INSTEAD OF
Trigger
trigger
event trigger
view
DML SQL
join
update
trigger INSTEAD OF
Oracle update,
insert delete
(base table)

14.1.2 Triggering Event


Triggering Event statement
INSERT, UPDATE DELETE
- UPDATE

Trigger
INSERT
DELETE

- Triggering Event
DML

.

Chap. 14

DML

14.1.3

Trigger Type

trigger 2
trigger statement
- Statement Trigger trigger
event
event

- Row Trigger trigger


event
triggering event
row trigger
SQL
SQL> INSERT INTO dept (deptno, dname, loc)
VALUES (50, EDUCATION, NEW YPRK);
statement trigger
row trigger

SQL
SQL> UPDATE emp SET sal = sal * 1.1 WHERE
deptno = 30;
row trigger

WHERE
trigger time
triger type
BEFORE INSERT row
BEFORE INSERT statement
AFTER INSERT row
AFTER INSERT statement
BEFORE UPDATE row
BEFORE UPDATE statement

.

Chap. 14

AFTER UPDATE row


AFTER UPDATE statement
BEFORE DELETE row
BEFORE DELETE statement
AFTER DELETE row
AFTER DELETE statement
INSTEAD OF row
INSTEAD OF statement

14.1.4 Trigger Body


Triggering
Event SQL
PL/SQL row triggers
()

trigger
14.2

Statement Trigger
Statement Trigger

CREATE [OR REPLACE] TRIGGER


trigger_name
timing event1 [ OR event2 OR event3]
ON table_name
PL/SQL block;
trigger_name trigger
timing BEFORE, AFTER INSTEAD OF
event data manipulation event
INSERT, UPDATE [OF column]
DELETE
table_name
PL/SQL block triggering body
BEFORE Statement
Trigger

.

Chap. 14

emp

Oracle Server roll back

RAISE_APPLICATION_ERROR
SQL> CREATE OR REPLACE TRIGGER
secure_emp
BEFORE INSERT ON emp
BEGIN
IF (TO_CHAR (sysdate, DY) IN (SAT,
SUN)) OR
(TO_CHAR(sysdate, HH24) NOT
BETWEEN 08 AND 18 ) THEN
RAISE_APPLICATION_ERROR (-20500,
You may only insert into EMP
during normal hours.);
END IF;
END;
/
EMP
(fire)
trigger
SQL*Plus
SQL> INSERT INTO EMP (empno, ename, deptno)
VALUES (7777, 'BAUWENS', 40);
INSERT INTO EMP (empno, ename, deptno)
VALUES (7777, 'BAUWENS', 40)
*
ERROR at line 1:
ORA-20500: You may only insert into EMP during
normal hours.
ORA-06512: at "SCOTT.SECURE_EMP", line 4

.

Chap. 14

ORA-04088: error during execution of trigger


'SCOTT.SECURE_EMP'
database
trigger trigger statement
roll back Oracle server
triggering event
event
trigger body conditional predicated
INSERTING, UPDATING DELETING
trigger
data manipulation

BEFORE Trigger
SQL> CREATE OR REPLACE TRIGGER
secure_emp
BEFORE INSERT OR UPDATE OR DELETE ON
emp
BEGIN
IF (TO_CHAER (sysdate, DY) IN (SAT,
SUN)) OR
(TO_CHAR(sysdate, HH24) NOT
BETWEEN 08 AND 18 ) THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (-20500,
You may only delete from EMP
during normal hours.);
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (-20500,
You may only insert into EMP
during normal hours.);
ELSIF UPDATING THEN
RAISE_APPLICATION_ERROR (-20500,
You may only update SAL EMP
during normal hours.);

.

Chap. 14

20500,

10

ELSE RAISE_APPLICATION_ERROR (You may only UPDATE EMP during

normal hours.);
END IF;
END;
/
AFTER
trigger
update sal
emp update

SQL> CREATE OR REPLACE TRIGGER


check_salary_count
AFTER UPDATE OF sal ON emp
DECLARE
v_salary_changes NUMBER;
v_max_changes
NUMBER;
BEGIN
SELECT upd, max_upd INTO
v_salary_changes, v_max_changes
FROM audit_table WHERE user_name =
user
AND table_name = EMP AND
column_name = SAL;
IF v_salary_changes > v_max_changes
THEN
RAISE_APPLICATION_ERROR(-20501,
You may only make a maximum of
||
TO_CHAR(v_max_changes) ||
changes to SAL column);
END IF;
END;

.

Chap. 14

11

/
AUDIT_TABLE
USER_N TABLEN COLUMN_N IN UP DE MAX_I MAX_U MAX_D
AME
AME
AME
S D L NS
PD
EL
SCOTT

EMP

SCOTT

EMP

JONES

EMP

14.3

1 1

1 5

SAL

5
0 0

0 5

Row Trigger
Row Trigger
CREATE [OR REPLACE] TRIGGER trigger_name
timing event1 [ OR event2 OR event3]
ON table_name
[REFERENCING OLD AS old | NEW AS new
FOR EACH ROW
[WHEN condition]
PL/SQL block;

trigger_name trigger
timing BEFORE, AFTER
event data manipulation event
INSERT, UPDATE [OF column]
DELETE
table_name
PL/SQL block triggering body
REFERENCING

default NEW OLD
FOR EACH ROW trigger
row trigger
WHEN
trigger body

Chap. 14

12

After row trigger


data manipulation
operation
SQL>CREATE OR REPLACE TRIGGER audit_emp
AFTER DELETE OR INSERT OR UPDATE ON
emp
FOR EACH ROW
BEGIN
IF DELETING THEN
UPDATE audit_table SET del = del + 1
WHERE user_name = user
AND
table_name = EMP AND column_name IS
NULL;
ELSIF INSERTING THEN
UPDATE audit_table SET ins = ins + 1
WHERE user_name = user
AND
table_name = EMP AND column_name IS
NULL;
ELSIF UPDATING THEN
UPDATE audit_table SET upd = upd + 1
WHERE user_name = user
AND
table_name = EMP AND column_name =
SAL;
ELSE
/* The data manipulation operation
is a general UPDATE */
UPDATE audit_table SET upd = upd + 1
WHERE user_name = user
AND table_name
= EMP AND column_name IS NULL;
END IF;
END;
/
trigger
AUDIT_EMP_VALUES

Chap. 14

13

EMP
OLD NEW

SQL>CREATE OR REPLACE TRIGGER


audit_emp_values
AFTER DELETE OR INSERT OR UPDATE ON
emp
FOR EACH ROW
BEGIN
INSERT INTO audit_emp_values
(user_name, timestamp, id, old_last_name,
new_last_name, old_title,
new_title, old_salary, new_salary)
VALUES (USER, SYSDATE, :OLD.empno,
:OLD.ename, :NEW.ename,
:OLD.job, :NEW.job, :OLD.sal,
:NEW.sal);
END;
/

row trigger NEW OLD

Data
Operatio
n
INSERT
UPDATE
DELETE

Old Value

New Value

NULL
Value before
update
Value before
update

Inserted value
Value after
update
NULL

- OLD NEW trigger

ROW Trigger

Chap. 14

14

- ( : )

OLD NEW SQL


PL/SQL
- ( : )
OLD NEW
WHEN
WHEN
trigger
WHEN

SQL>CREATE OR REPLACE TRIGGER


derive_commision_pct
AFTER DELETE OR INSERT OR UPDATE ON
emp
FOR EACH ROW
WHEN (NEW.job = SALESMAN)
BEGIN
IF INSERTING THEN :NEW.comm := 0;
ELSE
IF :OLD.comm IS NULL THEN
:NEW.comm := 0
ELSE
:NEW.comm := :OLD.comm *
(:NEW.sal / :OLD.sal);
END IF;
END IF;
END;
/

14.4 Trigger Mode: Enable or


Disable
Trigger enable


.

Chap. 14

15

trigger Oracle Server


integrity constraints trigger
integrity constraint

trigger
() trigger

disable re-enable trigger


ALTER TRIGGER
ALTER TRIGGER trigger_name DISABLE |
ENABLE
disable re-enable trigger
ALTER TABLE

ALTER TABLE table_name DISABLE |


ENABLE ALL TRIGGERS
trigger
ALTER TRIGGER
ALTER TRIGGER trigger_name COMPILE
trigger DROP
trigger
DROP TRIGGER trigger_name
14.5

Trigger Execution Model


Constraint Checking

Triggering event trigger


integrity
constraint triggers
trigger
(cascading trigger)

SQL
exception trigger

.

Chap. 14

16

exception handling
SQL
rolled back trigger
integrity constraints
trigger

trigger
- primary key,
foreign key, Unique key
constraining table
- mutating
table
constraining table
triggering event

SQL referential integrity


constraint trigger STATEMENT
trigger constraining

constraining table
DEPTNO DEPT
parent table cascading update
EMP
run time error

Chap. 14

17

Trigger parent key

DEPT cascade EMP


SQL>CREATE OR REPLACE TRIGGER
cascading_updates
AFTER UPDATE OF deptno ON DEPT
FOR EACH ROW
BEGIN
UPDATE emp SET emp.deptno =
:new.deptno
WHERE emp.deptno = :old.deptno;
END;
/
error
DEPT
SQL> UPDATE dept SET deptno = 1 WHERE
deptno = 30;
DEPT
triggering event ( DEPT
triggered table) EMP
foreign key foreign key constraint (
EMP constraining table) trigger

.

Chap. 14

cascading_updates
constraining table
mutating table
UPDATE,
DELETE INSERT
DELETE
CASCADE referential integrity
STATEMENT Trigger
mutating table
triggered table
FOREIGN KEY constraint
mutating table trigger
mutating table
row trigger
inconsistent
Trigger CHECK_SALARY

EMP

SQL>CREATE OR REPLACE TRIGGER


check_salary
BEFORE INSERT OR UPDATE OF sal, job ON
emp
FOR EACH ROW
DECLARE
v_minsalary
emp.sal%TYPE;
v_maxsalary emp.sal%TYPE;
BEGIN
SELECT MIN(sal), MAX(sal) INTO
v_minsalary, v_maxsalary FROM emp
WHERE job = :new.job;
IF :new.sal < v_minsalary OR :new.sal >
v_ maxsalary THEN

.

18

Chap. 14

19

RAISE_APPLICATION_ERROR(-20505,
Out of range);
END IF;
END;
/
SQL
SQL> UPDATE emp SET sal = 1500 WHERE
ename = SMITH;

runtime error
EMP mutating table trigger

14.6

Triggers

trigger

Oracle server
- Security: Oracle server
user role trigger

Chap. 14

20

- Auditing: Oracle server

trigger

- Data Integrity: Oracle server


integrity
constraints trigger integrity

- Referential Integrity: Oracle server

referential integrity trigger integrity

- Table Replication: Oracle server


asynchronous snapshots
trigger
synchronous replicas
- Derived data: Oracle server
(manually)
trigger

- Event logging: Oracle


server event trigger
events

14.6.1 Security
Oracle server
schemas role
schema
SQL> GRANT SELECT, INSERT, UPDATE, DELETE
ON emp
TO CLERK
-- database roles
SQL> GRANT CLERK TO SCOTT;
trigger



.

Chap. 14

21

SQL>CREATE OR REPLACE TRIGGER secure_emp


BEFORE INSERT OR UPDATE OR DELETE ON
emp
DECLARE
v_dummy VARCHAR2(1);
BEGIN
IF TO_CHAR(sysdate, DY IN (SUN, SAT) )
THEN
RAISE_APPLICATION_ERROR (-20506,
You may only change data during
normal bussinesses hours.);
END IF;
SELECT COUNT(*) INTO v_dummy FROM
holiday
WHERE holiday_date =
TRUNC(sysdate);
IF v_dummy > 0 THEN
RAISE_APPLICATION_ERROR (-20507,
You may not change data on
holiday.);
END IF;
END;
/

14.6.2 Auditing
audit Oracle server
AUDIT auditing feature
enable DBA
audit trial audit table

data dictionary views

.

Chap. 14

22

USER_AUDIT_OBJECT, USER_AUDIT_SESSION,
USER_AUDIT_STATEMENT
AUDIT
Oracle

14.6.3 Data integrity


data integrity Oracle server


emp 500
SQL
SQL> ALTER TABLE emp ADD CONSTRAINT
ck_salary CHECK (sal >= 500);
trigger

10 %
SQL> CREATE OR REPLACE TRIGGER
check_salary
BEFORE UPDATE OF sal ON emp
FOR EACH ROW
WHEN (new.sal < old.sal) OR (new.sal >
old.sal * 1.1)
BEGIN
RAISE_APPLICATION_ERROR(-20508,
Do not decrease nor increase by
more than 10%.);
END;

14.6.4 Referential Integrity


Referential Integrity

cascading trigger
referential integrity

cascading delete

.

Chap. 14

23

delete
null default
trigger DEPTNO
DEPT
EMP (- trigger
referential integrity
EMP DEPT
)
SQL> CREATE OR REPLACE TRIGGER
cascade_updates
AFTER UPDATE OF deptno ON dept
FOR EACH ROW
BEGIN
UPDATE emp SET emp.deptno =
:new.deptno
WHERE emp.deptno = :old.deptno;
END;
/
14.6.5
Table Replication

14.6.6 Derived data


derived data
batch job

SQL
SQL> UPDATE dept
SET total_sal = (SELECT SUM(salary)
FROM emp WHERE
emp.deptno = dept.deptno);

TOTAL_SALARY DEPT

.

Chap. 14

trigger
real time (synchronously)

global package trigger

SQL> CREATE OR REPLACE PROCEDURE


increment_salary
(v_id
IN dept.deptno%TYPE,
v_salary IN dept.total_salary%TYPE)
IS
BEGIN
UPDATE dept SET total_sal =
NVL(total_sal, 0) + v_salary
WHERE deptno = v_id;
END increment_salary;
/
SQL> CREATE OR REPLACE TRIGGER
compute_salary
AFTER INSERT OR UPDATE OF sal OR
DELETE ON emp
FOR EACH ROW
BEGIN
IF DELETING THEN
increment_salary(:old.deptno, -1
* :old.sal);
ELSIF UPDATING THEN
increment_salary(:new.deptno,
:new.sal - :old.sal);
ELSE /* inserting */
increment_salary(:new.deptno, :new.sal);
END IF;
END;
/

14.6.7 Event logging



.

24

Chap. 14

25

EVENT LOGGING server


()

package Oracle
package DBMS_MAIL e-mail

e-mail trigger

(transparently)
trigger

SQL>CREATE OR REPLACE TRIGGER


notify_reorder_rep
AFTER UPDATE OF amount_in_stock,
reorder_point ON inventory
FOR EACH ROW
WHEN new.amount_in_stock <=
new.reorder_point
DECLARE
v_descrip product.descrip%TYPE;
v_msg_text VARCHAR2(2000);
BEGIN
SELECT descrip INTO v_descrip
FROM PRODUCT WHERE proid =
:new.product_id;
v_msg_text := It has come to my
personal attention that, due to recent
CHR(10) || transactions, our
inventory for product # ||
TO_CHAR(:new.product_id) || --- ||
v_name || has fallen||
CHR(10) || CHR(10) || Yours, ||
CHR(10) || user || .;

.

Chap. 14

26

DBMS_MAIL.send(Invemtory,
user, null, null, Low Inventory,
null, v_msg_text);
END;
/
CHR(10) carriage return
14.7

trigger (Enabling
and Disabling Trigger)

trigger
(enable)

trigger (disable)


trigger
trigger
alter trigger enable

ALTER ANY TRIGGER



ALTER TRIGGER triggerName {ENABLE |
DISABLE}
triggerName trigger enable
disable
trigger
SQL> ALTER TRIGGER notify_reorder_rep
DISABLE;
enable disable trigger

ALTER TABLE {ENABLE|DISABLE } ALL


TRIGGER

.

Chap. 14

27

SQL> ALTER TABLE inventory ENABLE ALL


TRIGGERS;
SQL> ALTER TABLE inventory DISABLE ALL
TRIGGERS;
trigger
DROP TRIGGER trigger
trigger
DROP ANY TRIGGER
SQL> DROP TRIGGER notify_reorder_rep;
14.8

Trigger

Ledger

SQL> DESC ledger


Name
Null?
Type
----------------------------------------- ----------------------------------ACTIONDATE
NOT NULL
DATE
ACTION
NOT NULL
VARCHAR2(8)
ITEM
NOT NULL
VARCHAR2(30)
QUANTITY
NOT NULL
NUMBER(10)
QUANTITYTYPE
NOT NULL
VARCHAR2(10)
RATE
NOT NULL
NUMBER(10)
AMOUNT
NOT NULL
NUMBER(9,2)
PERSON
NOT NULL
VARCHAR2(25)

.

Chap. 14

28

1
Amount 10
% ledger trigger
(row level trigger) BEFORE UPDATE
Amount
10
new
old
CREATE TRIGGER ledger_bef_upd_row
BEFORE UPDATE ON ledger
FOR EACH ROW
WHEN (NEW.Amount / OLD.Amount > 1.1)
BEGIN
INSERT INTO ledger _audit
VALUES ( :old.ActionDate, :old.Action,
:old.Item, :old.Quantity,
:old.QuantityType, :old.Rate,
:old.Amount, :old.Person);
END;
trigger BEGIN
END
UPDATE ledger
WHEN
ledger ledger_audit
trigger ledger_audit
trigger
roles

NEW
OLD PL/SQL
colon ( : )
1
ledger

.

Chap. 14

29

ledger_audit trigger
ledger_audit

ledger triger INSTEAD OF
trigger INSTEAD OF
ledger
trigger insert, update
delete
trigger
trigger
2 trigger
INSERT UPDATE

UPDATE trigger
Amount
if (insert
update)
CREATE TRIGGER ledger_bef_upd_ins_row
BEFORE INSERT OR UPDATE OF Amount ON
ledger
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO ledger_audit
VALUES ( :new.ActionDate, :new.Action,
:new.Item, :new.Quantity,
:new.QuantityType, :new.Rate,
:new.Amount, :new.Person);
ELSE
-- if not inserting, then we are
updating Amount
INSERT INTO ledger_audit
VALUES ( :old.ActionDate, :old.Action,
:old.Item, :old.Quantity,

.

Chap. 14

30

:old.QuantityType, :old.Rate,
:old.Amount, :old.Person);
END IF;
END;
trigger
IF
INSERTING,
DELETING UPDATING
trigger
INSERT UPDATE
ledger
UPPER(Person)
( UpperPerson)

derived data
Person
UPPER(Person)
NULL

trigger
trigger BEFORE INSERT BEFORE UPDATE

3
CREATE TRIGGER ledger_bef_upd_ins_row
BEFORE INSERT OR UPDATE OF Person ON
ledger
FOR EACH ROW
BEGIN
:new.UpperPerson := :new.Person;
END;
trigger



.

Chap. 14

31

RAISE_APPLICATION_ERROR
trigger
4 trigger
(statement level trigger) BEFORE DELETE
ledger
DELETE
trigger

(username)
FIN
CREATE TRIGGER ledger_bef_del
BEFORE DELETE ON ledger
DECLARE
weekend_error EXCEPTION
BEGIN
IF TO_CHAR(Sysdate, DY) = SAT OR
TO_CHAR(Sysdate, DY) = SUN THEN
RAISE weekend_error;
END IF;
IF SUBSTR(User, 1, 3) <> FIN THEN
RAISE not_finance_user;
END IF;
EXCEPTION
WHEN weekend_error THEN
RAISE_APPLICATION_ERROR( -20001,
Deletions not allowed on weekends);
WHEN not_finance_user THEN
RAISE_APPLICATION_ERROR( -20002,
Deletions only allowed by Finance user);
END;

.

Chap. 14

32

You might also like