(八)Oracle学习笔记—— 触发器
1. 触发器简介
触发器在数据库里以独立的对象存储,类似于过程(procedure)和函数(function),都有声明,执行和异常处理过程的PL/SQL块。它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。 所以运行触发器就叫触发或点火(firing)。ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了触发ORACLE,如数据库的启动与关闭等。所以触发器常用来完成由数据库的完整性约束难以完成的复杂业务 规则的约束,或用来监视对数据库的各种操作,实现审计的功能。
2.触发器创建语法
- CREATE [OR REPLACE] TRIGGER trigger_name
- {BEFORE | AFTER }
- {INSERT | DELETE | UPDATE [OF column [, column …]]}
- [OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
- ON [schema.]table_name | [schema.]view_name
- [REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
- [FOR EACH ROW ]
- [WHEN condition]
- PL/SQL_BLOCK | CALL procedure_name;
2.1 语句解释
BEFORE 和 AFTER 指出触发器的触发时序分别为前触发和后触发方式,前触发是在执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建的触发器。
FOR EACH ROW 选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操作影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则只能为行触发器。
REFERENCING 子句说明相关名称,在行触发器的PL/SQL块和 WHEN 子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为 OLD 和 NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在 WHEN 子句中则不能加冒号。
WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只能用在 BEFORE 和 AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。
当一个基表被修改( INSERT, UPDATE, DELETE)时要执行的存储过程,执行时根据其所依附的基表改动而自动触发,因此与应用程序无关,用数据库触发器可以保证数据的一致性和完整性。
2.2 每张表最多可建立12 种类型的触发器,它们是:
- BEFORE INSERT
- BEFORE INSERT FOR EACH ROW
- AFTER INSERT
- AFTER INSERT FOR EACH ROW
- BEFORE UPDATE
- BEFORE UPDATE FOR EACH ROW
- AFTER UPDATE
- AFTER UPDATE FOR EACH ROW
- BEFORE DELETE
- BEFORE DELETE FOR EACH ROW
- AFTER DELETE
- AFTER DELETE FOR EACH ROW
3.触发器组成
触发事件:引起触发器被触发的事件。 例如:DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、数据库系统事件(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。
触发时间:即该TRIGGER 是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也就是触发事件和该TRIGGER 的操作顺序。
触发操作:即该TRIGGER 被触发之后的目的和意图,正是触发器本身要做的事情。 例如:PL/SQL 块。
触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,才会执行触发操作。
触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发器,使其执行触发操作。
触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;
行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
4.触发器编写注意事项
- 触发器不接受参数。
- 一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
- 在一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。
- 触发器最大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。
- 在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)。
- 触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。
- 在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。
- 在触发器主体中不能申明任何Long和blob变量。新值new和旧值old也不能是表中的任何long和blob列。
- 不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器)的语法格式和作用有较大区别。
5.触发器应用示例
5.1 触发器案例一:实施复杂的安全性校验
- --触发器应用场景一:实施复杂的安全性校验
- --禁止在非工作时间插入新员工
- /*
- 1.周末:to_char(sysdate,'day') in ('星期六','星期日')
- 2.上班前,下班后:to_number(to_char(sysdate,'hh24')) not between 9 and 18
- */
- create or replace trigger securityemp
- before insert
- on emp
- begin
- if to_char(sysdate,'day') in ('星期六','星期日') or
- to_number(to_char(sysdate,'hh24')) not between 9 and 18 then
- --禁止insert新员工
- raise_application_error(-20001,'禁止在非工作时间插入新员工');
- end if;
- end;
5.2 触发器案例二: 数据的确认
- --触发器案例二: 数据的确认
- /*
- 行级触发器针对的是记录,语句级触发器针对的是表。
- 案例一不允许在非工作时间插入新员工,不论是插入一条记录还是多条记录,触发器中的子程序都只需要执行一次,如果不符合条件,则不允许对整个表进行操作,即针对整个表只需要执行一次子程序,所以这里用的是语句级触发器;
- 案例二涨后的工资不能低于涨前的工资,在对每一个员工涨工资时都需要执行触发器中的子程序,来判断是否涨后的工资低于涨前的工资,即针对每条记录都要执行子程序,所以这里用的是行级触发器。
- 在行级触发器中使用:old和:new伪记录变量,识别值的状态。
- :old 表示操作这行记录前这行记录的值;
- :new 表示操作这行记录之后这行记录的值。
- 比如 :new.sal可以表示操作这行记录后该行中sal的值。
- */
- create or replace trigger check_salary
- before update
- on emp
- for each row --行级
- begin
- if :new.sal<:odl.sal then
- raise_application_error(-20002,'涨后薪水不能少于涨前薪水。 涨后薪水为:'||:new.sal ||'涨前的薪水:'||:old.sal);
- end if;
- end;
5.3 触发器案例三:数据的审计
- --触发器应用场景三:数据的审计——>基于值的审计功能
- --给员工涨工资,当涨后的薪水超过6000块时候,审计该员工的信息
- --创建表,用于保存审计信息
- create table audit_info(
- information varchar2(200)
- );
- create or replace trigger do_audit_emp_salary
- after update
- on emp
- for each row
- begin
- if :new.sal>6000 then
- insert into audit_info values(:new.empno||' '||:new.ename||' '||:new.sal);
- end if;
- end;
5.4 触发器案例四: 数据的备份和同步
- --触发器案例四: 数据的备份和同步
- --当给员工涨完工资后,自动备份新的工资资料到备份表中
- create or replace trigger trigger_sync_salary
- after update
- on emp
- for each row
- begin
- update emp_back set sal=:new.sal where empno=:new.empbo;
- end;
6. 触发器的配置
- --触发器创建后只要你不删除是会存在的,但是你可以自己控制它是否起作用。如:
- ALTER TRIGGER trigger_name DISABLE; -- 失效,生效改为enable
- ALTER TABLE table_name DISABLE ALL TRIGGERS; -- 批量失效,批量生效改为enable
- ALTER TRIGGER trigger_name COMPILE; -- 重新编译trigger
- DROP TRIGGER trigger_name; -- 删除trigger
(八)Oracle学习笔记—— 触发器的更多相关文章
- Oracle学习笔记—数据字典和常用命令(转载)
转载自: oracle常用数据字典和SQL语句总结 Oracle常用命令大全(很有用,做笔记) 一.Oracle数据字典 数据字典是Oracle存放有关数据库信息的地方,其用途是用来描述数据的.比如一 ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- 20145213《Java程序设计》第八周学习笔记
20145213<Java程序设计>第八周学习笔记 教材学习内容总结 "桃花春欲尽,谷雨夜来收"谷雨节气的到来意味着寒潮天气的基本结束,气温回升加快.刚出冬的我对于这种 ...
- oracle学习笔记第一天
oracle学习笔记第一天 --oracle学习的第一天 --一.几个基础的关键字 1.select select (挑选) 挑选出显示的--列--(可以多列,用“,”隔开,*表示所有列),为一条 ...
- 《Linux内核分析》第八周学习笔记
<Linux内核分析>第八周学习笔记 进程的切换和系统的一般执行过程 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163 ...
- 20165326 java第八周学习笔记
第八周学习笔记 知识点总结 1.进程与线程 进程:程序的一次动态执行过程 区别:进程和线程的区别? 进程是资源的分配和调度的一个独立单元,而线程是CPU调度的基本单元 同一个进程中可以包括多个线程,并 ...
- Oracle学习笔记——点滴汇总
Oracle学习笔记——点滴汇总 http://www.botangdb.com/ Oracle GI = Grid Infrastructure = ASM + Cluster
- Oracle学习笔记之四sp1,Oracle 11g的常用函数
从Oracle学习笔记之四,SQL语言入门中摘出来的,独立成一章节 3.1 字符类函数 ASCII(c)和CHR(i) 分别用于返回一个字符的ASCII码和返回给定ASCII值所对应的字符. C ...
- Oracle学习笔记之四,SQL语言入门
1. SQL语言概述 1.1 SQL语言特点 集合性,SQL可以的高层的数据结构上进行工作,工作时不是单条地处理记录,而对数据进行成组的处理. 统一性,操作任务主要包括:查询数据:插入.修改和删除数据 ...
随机推荐
- 【BZOJ 2124】【CodeVS 1283】等差子序列
http://www.lydsy.com/JudgeOnline/problem.php?id=2124 http://codevs.cn/problem/1283/ 重点是把判断是否存在3个数组成等 ...
- luogu P1047 校门外的树
题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……,L,都种 ...
- [NOIP2017]时间复杂度(模拟)
sscanf读入数字,getline(cin,string)读一整行,其余暴力模拟即可. #include<cstdio> #include<string> #include& ...
- 【最大流】POJ3236-ACM Computer Factory
[题意] 装配一个电脑需要P个零件,现在给出N机器的信息,每个机器可以将k个电脑由状态{S1,S2..,Sp}转变为{Q1,Q2..,Qp},问最多能装配多少台电脑以及对应的方案? [思路] 1A.. ...
- JDK源码学习笔记——Integer
一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...
- Java高级架构师(一)第39节:Nginx的Rewrite模块
- 一段javascript设计模式应用场景
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- mysql-mmm故障整理
Auth: JinDate: 20140414 1.master-slave同步问题1)故障描述和错误代码:监控报警slave故障登录slave服务器查看mysql> show slave st ...
- vmware 下 ubuntu 不能全屏显示 的解决方法
vmware 下 ubuntu 不能全屏显示 在 vmware 下 安装 ubuntu后,默认分辨率是 800 * 600,可以设置以全屏显示: 设置步骤: vmware 下启动 虚拟机,即 启动 u ...
- python灰帽子学习感想
Gray Hat Python Python Programming for hackers and reverse engineers Python灰帽子:黑客与逆向project师的Python编 ...