| The following sections illustrate an example of each type
of trigger.
The following is an example of a simple before statement-level
trigger that displays a message prior to an insert operation
on the emp table.
CREATE OR REPLACE TRIGGER emp_alert_trig
BEFORE INSERT ON emp
BEGIN
DBMS_OUTPUT.PUT_LINE('New employees are about to be added');
END;
The following INSERT is constructed so that
several new rows are inserted upon a single execution of the
command. For each row that has an employee id between 7900 and
7999, a new row is inserted with an employee id incremented by
1000. The following are the results of executing the command
when three new rows are inserted.
INSERT INTO emp (empno, ename, deptno) SELECT empno + 1000, ename, 40
FROM emp WHERE empno BETWEEN 7900 AND 7999;
New employees are about to be added
SELECT empno, ename, deptno FROM emp WHERE empno BETWEEN 8900 AND 8999;
EMPNO ENAME DEPTNO
---------- ---------- ----------
8900 JAMES 40
8902 FORD 40
8934 MILLER 40
The message,
New employees are about to be added, is
displayed once by the firing of the trigger even though the
result is the addition of three new rows.
The following is an example of an after statement-level trigger.
Whenever an insert, update, or delete operation occurs on the
emp table, a row is added to the
empauditlog table recording the date, user,
and action.
CREATE TABLE empauditlog (
audit_date DATE,
audit_user VARCHAR2(20),
audit_desc VARCHAR2(20)
);
CREATE OR REPLACE TRIGGER emp_audit_trig
AFTER INSERT OR UPDATE OR DELETE ON emp
DECLARE
v_action VARCHAR2(20);
BEGIN
IF INSERTING THEN
v_action := 'Added employee(s)';
ELSIF UPDATING THEN
v_action := 'Updated employee(s)';
ELSIF DELETING THEN
v_action := 'Deleted employee(s)';
END IF;
INSERT INTO empauditlog VALUES (SYSDATE, USER,
v_action);
END;
In the following sequence of commands, two rows are inserted
into the emp table using two
INSERT commands. The sal
and comm columns of both rows are updated
with one UPDATE command. Finally, both
rows are deleted with one DELETE command.
INSERT INTO emp VALUES (9001,'SMITH','ANALYST',7782,SYSDATE,NULL,NULL,10);
INSERT INTO emp VALUES (9002,'JONES','CLERK',7782,SYSDATE,NULL,NULL,10);
UPDATE emp SET sal = 4000.00, comm = 1200.00 WHERE empno IN (9001, 9002);
DELETE FROM emp WHERE empno IN (9001, 9002);
SELECT TO_CHAR(AUDIT_DATE,'DD-MON-YY HH24:MI:SS') AS "AUDIT DATE",
audit_user, audit_desc FROM empauditlog ORDER BY 1 ASC;
AUDIT DATE AUDIT_USER AUDIT_DESC
------------------ -------------------- --------------------
31-MAR-05 14:59:48 SYSTEM Added employee(s)
31-MAR-05 15:00:07 SYSTEM Added employee(s)
31-MAR-05 15:00:19 SYSTEM Updated employee(s)
31-MAR-05 15:00:34 SYSTEM Deleted employee(s)
The contents of the empauditlog table show
how many times the trigger was fired - once each for the two
inserts, once for the update (even though two rows were changed)
and once for the deletion (even though two rows were deleted).
The following example is a before row-level trigger that
calculates the commission of every new employee belonging
to department 30 that is inserted into the
emp table.
CREATE OR REPLACE TRIGGER emp_comm_trig
BEFORE INSERT ON emp
FOR EACH ROW
BEGIN
IF :NEW.deptno = 30 THEN
:NEW.comm := :NEW.sal * .4;
END IF;
END;
The listing following the addition of the two employees shows that
the trigger computed their commissions and inserted it as part of the
new employee rows.
INSERT INTO emp VALUES (9005,'ROBERS','SALESMAN',7782,SYSDATE,3000.00,NULL,30);
INSERT INTO emp VALUES (9006,'ALLEN','SALESMAN',7782,SYSDATE,4500.00,NULL,30);
SELECT * FROM emp WHERE empno IN (9005, 9006);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
9005 ROBERS SALESMAN 7782 01-APR-05 3000 1200 30
9006 ALLEN SALESMAN 7782 01-APR-05 4500 1800 30
The following example is an after row-level trigger.
When a new employee row is inserted, the trigger adds
a new row to the jobhist table for
that employee. When an existing employee is updated,
the trigger sets the enddate column
of the latest jobhist row (assumed
to be the one with a null enddate)
to the current date and inserts a new
jobhist row with the employee's
new information.
Finally, trigger adds a row to the
empchglog table with a description
of the action.
CREATE TABLE empchglog (
chg_date DATE,
chg_desc VARCHAR2(30)
);
CREATE OR REPLACE TRIGGER emp_chg_trig
AFTER INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW
DECLARE
v_empno emp.empno%TYPE;
v_deptno emp.deptno%TYPE;
v_dname dept.dname%TYPE;
v_action VARCHAR2(7);
v_chgdesc jobhist.chgdesc%TYPE;
BEGIN
IF INSERTING THEN
v_action := 'Added';
v_empno := :NEW.empno;
v_deptno := :NEW.deptno;
INSERT INTO jobhist VALUES (:NEW.empno, SYSDATE, NULL,
:NEW.job, :NEW.sal, :NEW.comm, :NEW.deptno, 'New Hire');
ELSIF UPDATING THEN
v_action := 'Updated';
v_empno := :NEW.empno;
v_deptno := :NEW.deptno;
v_chgdesc := '';
IF NVL(:OLD.ename, '-null-') != NVL(:NEW.ename, '-null-') THEN
v_chgdesc := v_chgdesc || 'name, ';
END IF;
IF NVL(:OLD.job, '-null-') != NVL(:NEW.job, '-null-') THEN
v_chgdesc := v_chgdesc || 'job, ';
END IF;
IF NVL(:OLD.sal, -1) != NVL(:NEW.sal, -1) THEN
v_chgdesc := v_chgdesc || 'salary, ';
END IF;
IF NVL(:OLD.comm, -1) != NVL(:NEW.comm, -1) THEN
v_chgdesc := v_chgdesc || 'commission, ';
END IF;
IF NVL(:OLD.deptno, -1) != NVL(:NEW.deptno, -1) THEN
v_chgdesc := v_chgdesc || 'department, ';
END IF;
v_chgdesc := 'Changed ' || RTRIM(v_chgdesc, ', ');
UPDATE jobhist SET enddate = SYSDATE WHERE empno = :OLD.empno
AND enddate IS NULL;
INSERT INTO jobhist VALUES (:NEW.empno, SYSDATE, NULL,
:NEW.job, :NEW.sal, :NEW.comm, :NEW.deptno, v_chgdesc);
ELSIF DELETING THEN
v_action := 'Deleted';
v_empno := :OLD.empno;
v_deptno := :OLD.deptno;
END IF;
INSERT INTO empchglog VALUES (SYSDATE,
v_action || ' employee # ' || v_empno);
END;
In the first sequence of commands shown below, two employees
are added using two separate INSERT commands
and then both are updated using a single UPDATE
command. The contents of the jobhist table
shows the action of the trigger for each affected row - two
new hire entries for the two new employees and two changed
commission records for the updated commissions on the two
employees. The empchglog table also
shows the trigger was fired a total of four times, once for
each action on the two rows.
INSERT INTO emp VALUES (9003,'PETERS','ANALYST',7782,SYSDATE,5000.00,NULL,40);
INSERT INTO emp VALUES (9004,'AIKENS','ANALYST',7782,SYSDATE,4500.00,NULL,40);
UPDATE emp SET comm = sal * 1.1 WHERE empno IN (9003, 9004);
SELECT * FROM jobhist WHERE empno IN (9003, 9004);
EMPNO STARTDATE ENDDATE JOB SAL COMM DEPTNO CHGDESC
---------- --------- --------- --------- ---------- ---------- ---------- ------------------
9003 31-MAR-05 31-MAR-05 ANALYST 5000 40 New Hire
9004 31-MAR-05 31-MAR-05 ANALYST 4500 40 New Hire
9003 31-MAR-05 ANALYST 5000 5500 40 Changed commission
9004 31-MAR-05 ANALYST 4500 4950 40 Changed commission
SELECT * FROM empchglog;
CHG_DATE CHG_DESC
--------- ------------------------------
31-MAR-05 Added employee # 9003
31-MAR-05 Added employee # 9004
31-MAR-05 Updated employee # 9003
31-MAR-05 Updated employee # 9004
Finally, both employees are deleted with a single
DELETE command. The
empchglog table now shows the trigger
was fired twice, once for each deleted employee.
DELETE FROM emp WHERE empno IN (9003, 9004);
SELECT * FROM empchglog;
CHG_DATE CHG_DESC
--------- ------------------------------
31-MAR-05 Added employee # 9003
31-MAR-05 Added employee # 9004
31-MAR-05 Updated employee # 9003
31-MAR-05 Updated employee # 9004
31-MAR-05 Deleted employee # 9003
31-MAR-05 Deleted employee # 9004
| |
---|