例3:利用ORACLE提供的条件谓词INSERTING、UPDATING和DELETING创建与例2具有相同功能的触发器。
BEGIN
DBMS_OUTPUT.PUT_LINE('插入前');
Disp_dept_summary();
DBMS_UTILITY.EXEC_DDL_STATEMENT(
'CREATE OR REPLACE TRIGGER trig2
AFTER INSERT OR DELETE OR UPDATE OF sal
ON emp
REFERENCING OLD AS old_emp NEW AS new_emp
FOR EACH ROW
DECLARE
I NUMBER;
BEGIN
IF UPDATING AND :old_emp.sal != :new_emp.sal THEN
DBMS_OUTPUT.PUT_LINE(''正在执行trig2 触发器…'');
DBMS_OUTPUT.PUT_LINE(''sal 旧值:''|| :old_emp.sal);
DBMS_OUTPUT.PUT_LINE(''sal 新值:''|| :new_emp.sal);
UPDATE dept_summary
SET sal_sum=sal_sum + :new_emp.sal - :old_emp.sal
WHERE deptno = :new_emp.deptno;
ELSIF INSERTING THEN
DBMS_OUTPUT.PUT_LINE(''正在执行trig2触发器…'');
SELECT COUNT(*) INTO I
FROM dept_summary
WHERE deptno = :new_emp.deptno;
IF I > 0 THEN
UPDATE dept_summary
SET sal_sum=sal_sum+:new_emp.sal,
Emp_count=emp_count+1
WHERE deptno = :new_emp.deptno;
ELSE
INSERT INTO dept_summary
VALUES (:new_emp.deptno, :new_emp.sal, 1);
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE(''正在执行trig2触发器…'');
SELECT emp_count INTO I
FROM dept_summary WHERE deptno = :old_emp.deptno;
IF I > 1 THEN
UPDATE dept_summary
SET sal_sum=sal_sum - :old_emp.sal,
Emp_count=emp_count - 1
WHERE deptno = :old_emp.deptno;
ELSE
DELETE FROM dept_summary
WHERE deptno = :old_emp.deptno;
END IF;
END IF;
END;'
);
INSERT INTO dept(deptno, dname, loc)
VALUES(90, 'demo_dept', 'none_loc');
INSERT INTO emp(ename, deptno, empno, sal)
VALUES(USER, 90, 9999, 3000);
INSERT INTO emp(ename, deptno, empno, sal)
VALUES(USER, 90, 9998, 2000);
DBMS_OUTPUT.PUT_LINE('插入后');
Disp_dept_summary();
UPDATE emp SET sal = sal*1.1 WHERE deptno=90;
DBMS_OUTPUT.PUT_LINE('修改后');
Disp_dept_summary();
DELETE FROM emp WHERE deptno=90;
DELETE FROM dept WHERE deptno=90;
DBMS_OUTPUT.PUT_LINE('删除后');
Disp_dept_summary();
DBMS_UTILITY.EXEC_DDL_STATEMENT('DROP TRIGGER trig2');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
DBMS_OUTPUT.PUT_LINE('插入前');
Disp_dept_summary();
DBMS_UTILITY.EXEC_DDL_STATEMENT(
'CREATE OR REPLACE TRIGGER trig2
AFTER INSERT OR DELETE OR UPDATE OF sal
ON emp
REFERENCING OLD AS old_emp NEW AS new_emp
FOR EACH ROW
DECLARE
I NUMBER;
BEGIN
IF UPDATING AND :old_emp.sal != :new_emp.sal THEN
DBMS_OUTPUT.PUT_LINE(''正在执行trig2 触发器…'');
DBMS_OUTPUT.PUT_LINE(''sal 旧值:''|| :old_emp.sal);
DBMS_OUTPUT.PUT_LINE(''sal 新值:''|| :new_emp.sal);
UPDATE dept_summary
SET sal_sum=sal_sum + :new_emp.sal - :old_emp.sal
WHERE deptno = :new_emp.deptno;
ELSIF INSERTING THEN
DBMS_OUTPUT.PUT_LINE(''正在执行trig2触发器…'');
SELECT COUNT(*) INTO I
FROM dept_summary
WHERE deptno = :new_emp.deptno;
IF I > 0 THEN
UPDATE dept_summary
SET sal_sum=sal_sum+:new_emp.sal,
Emp_count=emp_count+1
WHERE deptno = :new_emp.deptno;
ELSE
INSERT INTO dept_summary
VALUES (:new_emp.deptno, :new_emp.sal, 1);
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE(''正在执行trig2触发器…'');
SELECT emp_count INTO I
FROM dept_summary WHERE deptno = :old_emp.deptno;
IF I > 1 THEN
UPDATE dept_summary
SET sal_sum=sal_sum - :old_emp.sal,
Emp_count=emp_count - 1
WHERE deptno = :old_emp.deptno;
ELSE
DELETE FROM dept_summary
WHERE deptno = :old_emp.deptno;
END IF;
END IF;
END;'
);
INSERT INTO dept(deptno, dname, loc)
VALUES(90, 'demo_dept', 'none_loc');
INSERT INTO emp(ename, deptno, empno, sal)
VALUES(USER, 90, 9999, 3000);
INSERT INTO emp(ename, deptno, empno, sal)
VALUES(USER, 90, 9998, 2000);
DBMS_OUTPUT.PUT_LINE('插入后');
Disp_dept_summary();
UPDATE emp SET sal = sal*1.1 WHERE deptno=90;
DBMS_OUTPUT.PUT_LINE('修改后');
Disp_dept_summary();
DELETE FROM emp WHERE deptno=90;
DELETE FROM dept WHERE deptno=90;
DBMS_OUTPUT.PUT_LINE('删除后');
Disp_dept_summary();
DBMS_UTILITY.EXEC_DDL_STATEMENT('DROP TRIGGER trig2');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
例4:创建INSTEAD OF 触发器。首先创建一个视图myview, 由于该视图是复合查询所产生的视图,所以不能执行DML语句。根据用户对视图所插入的数据判断需要将数据插入到哪个视图基表中,然后对该基表执行插入操作。
DECLARE
No NUMBER;
Name VARCHAR2(20);
BEGIN
DBMS_UTILITY.EXEC_DDL_STATEMENT('
CREATE OR REPLACE VIEW myview AS
SELECT empno, ename, ''E'' type FROM emp
UNION
SELECT dept.deptno, dname, ''D'' FROM dept
');
-- 创建INSTEAD OF 触发器trigger3;
DBMS_UTILITY.EXEC_DDL_STATEMENT('
CREATE OR REPLACE TRIGGER trig3
INSTEAD OF INSERT ON myview
REFERENCING NEW n
FOR EACH ROW
DECLARE
Rows INTEGER;
BEGIN
DBMS_OUTPUT.PUT_LINE(''正在执行trig3触发器…'');
IF :n.type = ''D'' THEN
SELECT COUNT(*) INTO rows
FROM dept WHERE deptno = :n.empno;
IF rows = 0 THEN
DBMS_OUTPUT.PUT_LINE(''向dept表中插入数据…'');
INSERT INTO dept(deptno, dname, loc)
VALUES (:n.empno, :n.ename, ''none’’);
ELSE
DBMS_OUTPUT.PUT_LINE(''编号为''|| :n.empno||
''的部门已存在,插入操作失败!'');
END IF;
ELSE
SELECT COUNT(*) INTO rows
FROM emp WHERE empno = :n.empno;
IF rows = 0 THEN
DBMS_OUTPUT.PUT_LINE('’向emp表中插入数据…’’);
INSERT INTO emp(empno, ename)
VALUES(:n.empno, :n.ename);
ELSE
DBMS_OUTPUT.PUT_LINE(''编号为''|| :n.empno||
''的人员已存在,插入操作失败!'');
END IF;
END IF;
END;
');
INSERT INTO myview VALUES (70, 'demo', 'D');
INSERT INTO myview VALUES (9999, USER, 'E');
SELECT deptno, dname INTO no, name FROM dept WHERE deptno=70;
DBMS_OUTPUT.PUT_LINE('员工编号:'||TO_CHAR(no)||'姓名:'||name);
SELECT empno, ename INTO no, name FROM emp WHERE empno=9999;
DBMS_OUTPUT.PUT_LINE('部门编号:'||TO_CHAR(no)||'姓名:'||name);
DELETE FROM emp WHERE empno=9999;
DELETE FROM dept WHERE deptno=70;
DBMS_UTILITY.EXEC_DDL_STATEMENT('DROP TRIGGER trig3');
END;
No NUMBER;
Name VARCHAR2(20);
BEGIN
DBMS_UTILITY.EXEC_DDL_STATEMENT('
CREATE OR REPLACE VIEW myview AS
SELECT empno, ename, ''E'' type FROM emp
UNION
SELECT dept.deptno, dname, ''D'' FROM dept
');
-- 创建INSTEAD OF 触发器trigger3;
DBMS_UTILITY.EXEC_DDL_STATEMENT('
CREATE OR REPLACE TRIGGER trig3
INSTEAD OF INSERT ON myview
REFERENCING NEW n
FOR EACH ROW
DECLARE
Rows INTEGER;
BEGIN
DBMS_OUTPUT.PUT_LINE(''正在执行trig3触发器…'');
IF :n.type = ''D'' THEN
SELECT COUNT(*) INTO rows
FROM dept WHERE deptno = :n.empno;
IF rows = 0 THEN
DBMS_OUTPUT.PUT_LINE(''向dept表中插入数据…'');
INSERT INTO dept(deptno, dname, loc)
VALUES (:n.empno, :n.ename, ''none’’);
ELSE
DBMS_OUTPUT.PUT_LINE(''编号为''|| :n.empno||
''的部门已存在,插入操作失败!'');
END IF;
ELSE
SELECT COUNT(*) INTO rows
FROM emp WHERE empno = :n.empno;
IF rows = 0 THEN
DBMS_OUTPUT.PUT_LINE('’向emp表中插入数据…’’);
INSERT INTO emp(empno, ename)
VALUES(:n.empno, :n.ename);
ELSE
DBMS_OUTPUT.PUT_LINE(''编号为''|| :n.empno||
''的人员已存在,插入操作失败!'');
END IF;
END IF;
END;
');
INSERT INTO myview VALUES (70, 'demo', 'D');
INSERT INTO myview VALUES (9999, USER, 'E');
SELECT deptno, dname INTO no, name FROM dept WHERE deptno=70;
DBMS_OUTPUT.PUT_LINE('员工编号:'||TO_CHAR(no)||'姓名:'||name);
SELECT empno, ename INTO no, name FROM emp WHERE empno=9999;
DBMS_OUTPUT.PUT_LINE('部门编号:'||TO_CHAR(no)||'姓名:'||name);
DELETE FROM emp WHERE empno=9999;
DELETE FROM dept WHERE deptno=70;
DBMS_UTILITY.EXEC_DDL_STATEMENT('DROP TRIGGER trig3');
END;
例5:利用ORACLE事件属性函数,创建一个系统事件触发器。首先创建一个事件日志表eventlog,由它存储用户在当前数据库中所创建的数据