oracle数据库触发器(trigger)用法总结
from:http://blog.csdn.net/zhanzhib/article/details/48729417
触发器的意思就是当我们对数据库对象(一般是表或视图)进行insert、update、delete操作的时候,这些操作会相应的触发一些事件的执行,通常要执行的事件被写成PL/SQL程序,那么这些数据库对象上的事件相关的程序就是触发器(trigger)。Oracle数据库中,触发器分为before、after、instead of三种,其中before、after主要对于表操作,instead of主要对于视图操作,因为如果视图是多表的时候,不能直接进行DML操作,这个时候可以建立代替触发器(instead of)来替换事件本身的动作。同时,触发器也可以分为row级和statement级两种,row级的触发器在每次DML一行时执行,statement触发器一个SQL语句引发一次,不管影响几行。
图1:trigger的触发顺序
上图1非常重要,对于trigger的触发顺序的解释一目了然,尤其是下半副图,update数据的时候,对于statement trigger,不管是before还是after,都只会执行一次,而row trigger,却会在每次的udpate的前后执行一次。
1、before、after触发器
创建statement trigger和row trigger的语法直接看下面代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
-- statement级before trigger CREATE OR REPLACE TRIGGER secure_emp BEFORE INSERT OR DELETE OR UPDATE ON employees BEGIN IF (TO_CHAR(SYSDATE, 'DY' ) IN ( 'SAT' , 'SUN' )) OR (TO_CHAR(SYSDATE, 'HH24:MI' ) NOT BETWEEN '08:00' AND '18:00' ) THEN RAISE_APPLICATION_ERROR(-20500, 'You may modify EMPLOYEES table only on weekdays.' ); END IF; END ; -- row级before trigger CREATE OR REPLACE TRIGGER restrict_salary BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW BEGIN IF NOT (:NEW.job_id IN ( 'AD_PRES' , 'AD_VP' )) AND :NEW.salary > 15000 THEN RAISE_APPLICATION_ERROR(-20202, 'Error' ); END IF; END ; -- row级after trigger,注意:new和:old的用法 CREATE OR REPLACE TRIGGER audit_emp_values AFTER DELETE OR INSERT OR UPDATE ON employees FOR EACH ROW BEGIN INSERT INTO audit_emp_table (user_name, TIMESTAMP , id, old_last_name, new_last_name, old_title, new_title, old_salary, new_salary) VALUES ( USER , SYSDATE, :OLD.employee_id, :OLD.last_name, :NEW.last_name, :OLD.job_id, :NEW.job_id, :OLD.salary, :NEW.salary); END ; -- row级before trigger,注意when的用法 CREATE OR REPLACE TRIGGER derive_commission_pct BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW WHEN (NEW.job_id = 'SA_REP' ) BEGIN IF INSERTING THEN :NEW.commission_pct := 0; ELSIF :OLD.commission_pct IS NULL THEN :NEW.commission_pct := 0; ELSE :NEW.commission_pct := :OLD.commission_pct + 0.05; END IF; END ; |
对于:OLD和:NEW的用法,需要注意的是它们什么时候存在什么时候可用,:old表示引用以前的列值,:new表示引用最新的列值,这两个变量都只能在for each row存在的时候才可用,且update语句:old和:new都有,delete语句只有:old,insert语句只有:new。
2、instead of触发器
对于instead of触发器,一般都是用在复杂视图上,用于对复杂视图中相关表的更新操作。如下例所示(代码收录自网络):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
-- 创建表 CREATE TABLE STUDENT ( CODE VARCHAR2(5), LNAME VARCHAR2(200) ) CREATE TABLE COURSE ( CODE VARCHAR2(5), CNAME VARCHAR2(30) ) CREATE TABLE ST_CR ( STUDENT VARCHAR2(5), COURSE VARCHAR2(5), GRADE NUMBER ) -- 表的约束 ALTER TABLE STUDENT ADD CONSTRAINT STUDENT$PK PRIMARY KEY (CODE); ALTER TABLE COURSE ADD CONSTRAINT COURSE$PK PRIMARY KEY (CODE); ALTER TABLE ST_CR ADD CONSTRAINT ST_CR$PK PRIMARY KEY (STUDENT, COURSE); ALTER TABLE ST_CR ADD CONSTRAINT ST_CR$FK$STUDENT FOREIGN KEY (STUDENT) REFERENCES STUDENT(CODE); ALTER TABLE ST_CR ADD CONSTRAINT ST_CR$FK$COURSE FOREIGN KEY (COURSE) REFERENCES COURSE(CODE); -- 创建基于这三个表的视图 CREATE OR REPLACE VIEW STUDENT_STATUS AS SELECT S.CODE S_CODE, S.LNAME STUDENT, C.CODE C_CODE, C.CNAME COURSE, SC.GRADE GRADE FROM STUDENT S, COURSE C, ST_CR SC WHERE S.CODE = SC.STUDENT AND C.CODE = SC.COURSE -- 创建基于视图的instead of触发器 CREATE OR REPLACE TRIGGER TRI_STCR INSTEAD OF INSERT ON STUDENT_STATUS FOR EACH ROW DECLARE W_ACTION VARCHAR2(1); BEGIN IF INSERTING THEN W_ACTION := 'I' ; ELSE RAISE PROGRAM_ERROR; END IF; INSERT INTO STUDENT(CODE, LNAME) VALUES (:NEW.S_CODE,:NEW.STUDENT); INSERT INTO COURSE(CODE, CNAME) VALUES (:NEW.C_CODE, :NEW.COURSE); INSERT INTO ST_CR(STUDENT, COURSE, GRADE) VALUES (:NEW.S_CODE, :NEW.C_CODE, :NEW.GRADE); END ; -- 对视图执行数据插入,如果这里没有建过instead of触发器,很明显对复杂视图进行DML操作是会出错的 INSERT INTO STUDENT_STATUS(S_CODE, STUDENT, C_CODE, COURSE, GRADE) VALUES ( '001' , 'Mike' , 'EN' , 'English' ,86); |
3、管理Trigger
1
2
3
4
|
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数据库中trigger的使用,大概就是这样,虽然看着比较多,但是在实际中确是不太建议使用的,因为维护起来很不方便,所以在能不用trigger的地方还是不用为好。
2015年01月16日补充:
oracle对触发器提供了如下的一些谓词:
(1)inserting:当触发事件是insert时,取值为true,否则为false。
(2)updating[(column_1, column_2, ..., column_x)]:当触发事件是update时,如果修改了column_x列,则取值为true,否则为false。其中,column_x是可选的。
(3)deleting:当触发事件是delete时,则取值为true,否则为false。
oracle数据库触发器(trigger)用法总结的更多相关文章
- Oracle数据库——触发器的创建与应用
一.涉及内容 1.理解触发器的概念.作用和类型. 2.练习触发器的创建和使用. 二.具体操作 (实验) 1.利用触发器对在scott.emp表上执行的DML操作进行安全性检查,只有scott用户登录数 ...
- Oracle数据库触发器使用(删除触发)
当我们需要用到触发器的时候,还是很方便,你会指定当我在操作某一事件时触发效果完成我所希望完成的事情:这就是触发器, 下面我给大家上一串代码,这是一个当我在操作删除事件操作时候,我希望把即将删除那条数据 ...
- mysql 触发器 trigger用法 four
实验4 触发器 (1)实验目的 掌握数据库触发器的设计和使用方法 (2)实验内容和要求 定义BEFORE触发器和AFTER触发器.能够理解不同类型触发器的作用和执行原理,验证触发器的有效性. (3)实 ...
- mysql 触发器 trigger用法 two (稍微复杂的)
触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...
- mysql 触发器 trigger用法 three (稍微复杂的)
MySQL包含对触发器的支持.触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行. 创建触发器 在MySQL中,创建触发器语法如下 ...
- Oracle数据库---触发器
SQL> --当我们对empnew执行删除操作之后,它就会出现一个提示信息,提示:这是删除操作!SQL> CREATE TRIGGER first_trigger 2 AFTER DELE ...
- oracle 数据库触发器,插入更新时间戳
1.首先建立一个测试表 CREATE TABLE TestTragger( UserId int Primary Key, Name VARCHAR() Not Null, CreateTime Ti ...
- MySQL数据库触发器(trigger)
MySQL触发器(trigger):监视某种情况并触发某种操作 一:四要素 触发时间:before/after 地点:table 监视操作:insert/update/delete 触发操作:inse ...
- mysql 触发器 trigger用法 one (简单的)
实例~~ example1: 创建表tab1 1 2 3 4 DROP TABLE IF EXISTS tab1; CREATE TABLE tab1( tab1_id varchar(11) ...
随机推荐
- ubuntu 14.04英文环境设置成中文
适用于ubuntu 14.04英文版的系统,其它版本的设置应该是大同小异的. 进入ubuntu系统,在顶部齿状标志找到system... 2.在personal找到Language Support 3 ...
- Spark使用总结与分享【转】
背景 使用spark开发已有几个月.相比于python/hive,scala/spark学习门槛较高.尤其记得刚开时,举步维艰,进展十分缓慢.不过谢天谢地,这段苦涩(bi)的日子过去了.忆苦思甜,为了 ...
- 使用B或BL跳转时,下一条指令的地址的计算
.text .global _start 3_start: b step1 step1: ldr pc, =step2 step2: b step2 反汇编代码: : eaffffff b 0x4 : ...
- 用Python写一个猜数字游戏
2015.5.25第一天下载Python IDLE,写个猜数字的小游戏来熟悉这门语言: times=6 letters=[100] for i in range(1,times): a = input ...
- VBA学习笔记(6)--抽取第一列中叫“虹虹”的个人信息
说明(2017.3.25): 1. 知识点为dim arr2(1 to 1000, 1 to 4)先定义一个足够大的二维数组,不然后面需要transpose转置成一维数组. '抽取列表中叫“虹虹”的所 ...
- 在centos中安装mangodb
1.下载完安装包,并解压 tgz(以下演示的是 64 位 Linux上的安装) curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_6 ...
- PostMessage与PostThreadMessage的差别
消息队列是属于线程的,Post消息就是把消息放到目标线程的消息队列中. 这两者的差别在于: PostMessage 通过指定目标窗体句柄来确定目标线程,通常情况下由窗体过程来处理消息: PostThr ...
- 【WPF】设置ListBox容器Item的流式布局
需求:像下图那样显示把一组内容装入ListBox中显示.要求用WrapPanel横向布局,顺序如图中的数字. 问题:ListBox默认的布局是从上往下单列的,所以需要设置布局. <ListBox ...
- 解决javaWEB 下载文件中文名称乱码问题
response.setContentType("application/x-msdownload;"); response.setCharacterEncoding(" ...
- MySQL命令学习(二)
(13)where字句操作符 = 等于 <> 不等于 != 不等于 < 小于 > ...