首页 > 代码库 > 触发器五(建立INSTEAD OF触发器)(学习笔记)

触发器五(建立INSTEAD OF触发器)(学习笔记)

INSTEAD OF触发器

对于简单视图,可以直接执行INSERT,UPDATE和DELETE操作
但是对于复杂视图,不允许直接执行INSERT,UPDATE和DELETE操作。
为了在具有以上情况的复杂视图上执行DML操作需要征用触发器来完成

--创建复杂视图

CREATE OR REPLACE VIEW v_emp20 ASSELECT e.empno,e.ename,e.job,e.sal,d.deptno,d.dname,d.locFROM emp e,dept dWHERE e.deptno=d.deptno;--查看视图SELECT * FROM user_views;

 

INSTEAD OF触发器可以实现更新视图时多个数据表一起更新的问题

技术分享

instead-of触发器创建语法CREATE [OR REPLACE] TRIGGER 触发器名称    INSTEAD OF [INSERT | UPDATE | UPDATE OF 列名称 [,列名称,...] | DELETE] ON 视图名称    [FOR EACH ROW]    [WHEN 触发条件]    [DECLARE]        [程序声明部分 ;]    BEGIN        程序代码部分 ;    END [触发器名称] ;

替代触发器创建时不需要使用BEFORE或者AFTER,而将其替换为INSTEAD OF,同时操作的对象也有表替换为视图

 

示例一、创建一个insert替代触发器用于执行图添加操作

create or replace trigger view_insert_tigger  instead of insert on v_emp20    for each rowdeclare    v_empCount       NUMBER;    v_deptCount      NUMBER;begin    --判断要增加的员工是否存在    SELECT COUNT(empno) INTO v_empCount FROM emp WHERE empno=:NEW.empno;        --判断要部门是否存在    SELECT COUNT(deptno) INTO v_deptCount FROM dept WHERE deptno=:new.deptno;  --如果员工不存在  IF v_empCount=0 THEN      INSERT INTO emp(empno,ename,job,sal,deptno)      VALUES(:new.empno,:new.ename,:new.job,:new.sal,:new.deptno);    END IF;    --如果部门不存在    IF v_deptCount=0 THEN      INSERT INTO dept(deptno,dname,loc)VALUES(:new.deptno,:new.dname,:new.loc);    END IF;end view_insert_tigger;--添加数据INSERT INTO v_emp20(empno,ename,job,sal,deptno,dname,loc)VALUES(7777,张三丰,CLERK,800,77,活动部,深圳);

示例二、创建一个update替代触发器用于执行视图更新操作

create or replace trigger view_update_tigger  INSTEAD OF update on v_emp20    for each rowdeclare  begin  UPDATE emp SET ename=:new.ename,job=:new.job,sal=:new.sal WHERE empno=:NEW.empno;  UPDATE dept SET dname=:new.dname,loc=:new.loc WHERE deptno=:new.deptno;end view_update_tigger;UPDATE v_emp20 SET ename=任我行,sal=2000,dname=魔教 WHERE empno=7777;COMMIT;--查询SELECT * FROM v_emp20;

示例三、创建一个DELETE替代触发器用于执行视图的删除操作

create or replace trigger view_delete_tigger  instead of delete on v_emp20    for each rowdeclare  v_empCount          NUMBER;BEGIN  --判断员工是否存在 SELECT COUNT(empno) INTO v_empCount FROM emp WHERE empno=:old.empno;  --如果员工存在  IF v_empCount>0 THEN      DELETE FROM emp WHERE empno=:old.empno;    END IF;  end view_delete_tigger;--执行删除DELETE FROM v_emp20 WHERE empno=7777;COMMIT;--查询SELECT * FROM v_emp20;SELECT * FROM emp;

示例四、将以上三个合为一个

create or replace trigger view20emp_trigger  instead of INSERT OR UPDATE OR DELETE on v_emp20    for each rowdeclare  v_empCount            NUMBER;  v_deptCount            NUMBER;BEGIN  IF inserting THEN      --判断要增加的员工是否存在      SELECT COUNT(empno) INTO v_empCount FROM emp WHERE empno=:NEW.empno;      --判断要增加的部门是否存在      SELECT COUNT(deptno) INTO v_deptCount FROM dept WHERE deptno=:new.deptno;      --员工不存在就增加      IF v_empCount=0 THEN         INSERT INTO emp(empno,ename,job,sal,deptno)      VALUES(:new.empno,:new.ename,:new.job,:new.sal,:new.deptno);    END IF;    --如果部门不存在    IF v_deptCount=0 THEN      INSERT INTO dept(deptno,dname,loc)VALUES(:new.deptno,:new.dname,:new.loc);    END IF;        ELSIF updating THEN     UPDATE emp SET ename=:new.ename,job=:new.job,sal=:new.sal WHERE empno=:NEW.empno;  UPDATE dept SET dname=:new.dname,loc=:new.loc WHERE deptno=:new.deptno;    ELSIF deleting THEN        --判断员工是否存在 SELECT COUNT(empno) INTO v_empCount FROM emp WHERE empno=:old.empno;  --如果员工存在  IF v_empCount>0 THEN      DELETE FROM emp WHERE empno=:old.empno;    END IF;  ELSE    NULL;  END IF;  end view20emp_trigger;

执行增加、修改、删除

--添加数据INSERT INTO v_emp20(empno,ename,job,sal,deptno,dname,loc)VALUES(7777,张三丰,CLERK,800,77,活动部,深圳);--查询SELECT * FROM v_emp20;UPDATE v_emp20 SET ename=任我行,sal=2000,dname=魔教 WHERE empno=7777;COMMIT;--查询SELECT * FROM v_emp20;--执行删除DELETE FROM v_emp20 WHERE empno=7777;COMMIT;--查询SELECT * FROM v_emp20;SELECT * FROM emp;

当视图中包含以下结构之一,就表示为不可更新的视图,都不允许直接执行DML操作

1)具有集合操作符(UNION,UNION ALL,INTERSECT,MINUS);
2)具有分组函数(MIN,MAX,SUM,AVG,COUNT等)统计函数;
3)具有GROUP BY,CONNECT BY或START WITH等子句,HAVING 子句;
4)具有DISTINCT关键字;
5)具有连接查询(集合运算连接)

6)CASE 或者DECODE 语句

 

触发器五(建立INSTEAD OF触发器)(学习笔记)