INSTEAD OF触发器

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

--创建复杂视图

CREATE OR REPLACE VIEW v_emp20
AS
SELECT e.empno,e.ename,e.job,e.sal,d.deptno,d.dname,d.loc
FROM emp e,dept d
WHERE 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 row
declare
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 row
declare 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 row
declare
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 row
declare
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触发器)(学习笔记)的更多相关文章

  1. 实验楼课程管理程序-深入学习《C++ Primer第五版》实验报告&学习笔记1

    本片博客为实验楼的训练营课程深入学习<C++ Primer第五版>的实验报告和学习笔记. 原课程地址为:https://www.shiyanlou.com/courses/405# 原文出 ...

  2. sql 入门经典(第五版) Ryan Stephens 学习笔记  第四部分:建立复杂的数据库查询/

    第十三章: 在查询表里结合表 1.等值结合 : // 选择 tabla_a 和table_b 中id相等的行,输出 他们的id 和name select table_a.id , table_a.na ...

  3. 建立 Active Directory域 ----学习笔记

    第五章 建立 Active Directory域 1.工作组和域的理解 ​ a.工作组是一种平等身份环境,各个计算机之间各个为一个独立体,不方便管理和资源共享. ​ b.域环境一般情况下满足两类需求, ...

  4. sql 入门经典(第五版) Ryan Stephens 学习笔记 第五部分: 性能调整

    第十六章: 利用索引改善性能 1. create index 单字段索引:  create index index_name on table_name (column_name);唯一索引:     ...

  5. sql 入门经典(第五版) Ryan Stephens 学习笔记 (第六,七,八,九,十章,十一章,十二章)

    第六章: 管理数据库事务 事务 是 由第五章 数据操作语言完成的  DML ,是对数据库锁做的一个操作或者修改. 所有事务都有开始和结束 事务可以被保存和撤销 如果事务在中途失败,事务中的任何部分都不 ...

  6. sql 入门经典(第五版) Ryan Stephens 学习笔记 (第一,二,三,,四,五章)

    SQL - Structured  Query Language (结构化查询语言) 1/ SQL 命令的类型 : 数据定义语言: DDL 数据操作语言: DML 数据查询语言: DQL 数据控制语言 ...

  7. OSPF建立邻居、邻接关系 学习笔记

    Ospf中路由器之间存在两种连接关系:邻居关系和邻接关系.本博文将详细介绍这2种关系建立及工作原理. 如果两台路由器之间共享一条公共数据链路(两台路由器中间没有其它路由器,或者两台路由器之间存在虚连接 ...

  8. .NET 云原生架构师训练营(建立系统观)--学习笔记

    目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...

  9. sql 入门经典(第五版) Ryan Stephens 学习笔记 后续——存储引擎

    一.引擎基础 1 查看系统支持的存储引擎 show engines; 2 查看表使用的存储引擎两种方法: a.show table status from database_name where na ...

随机推荐

  1. tsinsen A1067. Fibonacci数列整除问题 dp

    A1067. Fibonacci数列整除问题 时间限制:1.0s   内存限制:512.0MB   总提交次数:2796   AC次数:496   平均分:51.83 将本题分享到:     查看未格 ...

  2. C#高级编程9-第2章 核心C#

    C#基础 使用C#命名编译器csc.exe,编译C#程序 变量 变量一般初始化后才能使用 类型判断弱类型var,根据初始值判断类型, 变量作用域,可以访问该代码的区域 类中定义的成员变量和属性,作用在 ...

  3. 原生+H5开发之:Android webview配置

    在上一篇文章Android 原生开发.H5.React-Native开发特点,我们可以了解到三种Android开发方式的区别和优缺点.[Android开发:原生+H5]系列的文章,将主要讲解Andro ...

  4. Linux 内核编译步骤及配置详解

    前言    Linux内核是操作系统的核心,也是操作系统最基本的部分. Linux内核的体积结构是单内核的.但是他充分采用了微内核的设计思想.使得虽然是单内核.但工作在模块化的方式下.并且这个模块可以 ...

  5. Spring <context:annotation-config/> 解说(转)

    在基于主机方式配置Spring的配置文件中,你可能会见到<context:annotation-config/>这样一条配置,他的作用是式地向 Spring 容器注册 AutowiredA ...

  6. 关于maven依赖中的<scope>provided</scope>使用

    今天开发web的时候,需要用到servlet-api,于是在pom.xml中添加依赖 <dependency> <groupId>javax.servlet</group ...

  7. C#程序集系列11,全局程序集缓存

    全局程序集缓存(GAC:Global Assembly Cache)用来存放可能被多次使用的强名称程序集.当主程序需要加载程序集的时候,优先选择到全局程序集缓存中去找寻需要的程序集. 为什么需要全局程 ...

  8. C#程序集系列02,使用记事本查看可执行程序集的IL代码

    继续上一篇"C#程序集系列01,用记事本编写C#,IL代码,用DOS命令编译程序集,运行程序",在F盘的as文件夹中已经有了若干程序集.本篇体验使用记事本查看可执行程序集的IL代码 ...

  9. 使用Dictionary泛型集合封装业务逻辑判断 z

    C#2.0 提供了Dictionary 泛型类,它提供了从一组键到一组值的映射.字典中的每个添加项都由一个值及其相关联的键组成.通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictio ...

  10. Web项目中获取SpringBean——在非Spring组件中获取SpringBean

    最近在做项目的时候我发现一个问题:Spring的IOC容器不能在Web中被引用(或者说不能被任意地引用).我们在配置文件中让Spring自 动装配,但并没有留住ApplicationContext的实 ...