参考网址:http://hi.baidu.com/bystander1983/item/f065c00cbe25508d03ce1b3b,原文稍微乱一些,感谢原作者的分享。
DML触发器
DDL触发器
系统触发器
替代触发器
1. 如果存在语句级BEFORE触发器,则先执行一次语句级BEFORE触发器。
2. 在SQL语句的执行过程中,如果存在行级BEFORE触发器,则SQL语句在对每一行操作之前,都要先执行一次行级BEFORE触发器,然后才对行进行操作。
如果存在行级AFTER触发器,则SQL语句在对每一行操作之后,都要再执行一次行级AFTER触发器。
3. 如果存在语句级AFTER触发器,则在SQL语句执行完毕后,要最后执行一次语句级AFTER触发器。
行级触发器对DML语句影响的每个行执行一次;
语句级触发器对每个DML语句执行一次,如果在TABLE表中插入的数据为500行,那么这个表上的语句级触发器只执行一次,而行级的触发器就要执行500次了。
若在触发器定义中出现FOR EACH ROW子句,则为行级触发器,否则为表级触发器(语句触发器).
DML触发器是定义在表上的触发器,有DML事件引发。
4.1 DML事件(3种)
INSERT 在表或视图中插入数据时触发
UPDATE 修改表或视图中的数据时触发
DELETE 在删除表或视图中的数据时触发
4.2 编写DML触发器的要素
确定触发的表,即在其上定义触发器的表
确定触发的事件,DML触发器的触发事件有INSERT、UPDATE和DELETE三种
确定触发时间。触发的时间有BEFORE和AFTER两种,分别表示触发动作发生在DML语句执行之前和语句执行之后
确定触发级别,有语句级触发器和行级触发器两种。语句级触发器表示SQL语句只触发一次触发器,行级触发器表示SQL语句影响的每一行都要触发一次
4.3 相关问题备注
1. 如果有多个触发器被定义成为相同时间、相同事件触发,且最后定义的触发器是有效的,则最后定义的触发器被触发,其他触发器不执行。
2. 一个触发器可由多个不同的DML操作触发。在触发器中,可用INSERTING、DELETING、UPDATING谓词来区别不同的DML操作。
这些谓词可以在IF分支条件语句中作为判断条件来使用。
3. 在行级触发器中,用:new 和:old(称为伪记录)来访问数据变更前后的值。
但要注意,INSERT语句插入一条新记录,所以没有:old记录,而DELETE语句删除掉一条已经存在的记录,所以没有:new记录。
UPDATE语句既有:old记录,也有:new记录,分别代表修改前后的记录。
引用具体的某一列的值的方法是: :old.字段名或:new.字段名。
触发器体内禁止使用COMMIT、ROLLBACK、SAVEPOINT语句,也禁止直接或间接地调用含有上述语句的存储过程。
4.4 创建触发器
CREATE [OR REPLACE] TRIGGER 触发器名 {BEFORE|AFTER|INSTEAD OF} 触发事件1 [OR 触发事件2...] ON 表名 WHEN 触发条件 [FOR EACH ROW] DECLARE 声明部分 BEGIN 主体部分 END;
其中:
OR REPLACE:表示如果存在同名触发器,则覆盖原有同名触发器。
BEFORE、AFTER和INSTEAD OF:说明触发器的类型。
WHEN 触发条件:表示当该条件满足时,触发器才能执行。
触发事件:指INSERT、DELETE或UPDATE事件,事件可以并行出现,中间用OR连接。
对于UPDATE事件,还可以用以下形式表示对某些列的修改会引起触发器的动作:
UPDATE OF 列名1,列名2...
ON 表名:表示为哪一个表创建触发器。
FOR EACH ROW:表示触发器为行级触发器,省略则为语句级触发器。
示例:
表:
很简单,只有一个ID,一个NAME
create table T_YGY_DEMO_BOOK2 ( ID NUMBER(11) not null, NAME VARCHAR2(100) not null )
1. 对表T_YGY_DEMO_BOOK2进行INSERT,UPDATE,DELETE操作时,输出相应的记录。
CREATE OR REPLACE TRIGGER TRI_YGY_BOOK2_LOG BEFORE INSERT OR UPDATE OR DELETE ON T_YGY_DEMO_BOOK2 BEGIN IF INSERTING THEN DBMS_OUTPUT.put_line('触发器日志:要添加一条记录'); ELSIF UPDATING THEN DBMS_OUTPUT.put_line('触发器日志:要修改一条记录'); ELSIF DELETING THEN DBMS_OUTPUT.put_line('触发器日志:要删除一条记录'); END IF; END; /
2. 对表T_YGY_DEMO_BOOK2进行更新操作时,判断ID是否大于5000,并输出不同的记录CREATE OR REPLACE TRIGGER TRI_YGY_BOOK2_VALUE BEFORE UPDATE ON T_YGY_DEMO_BOOK2 FOR EACH ROW BEGIN IF :OLD.ID>5000 THEN DBMS_OUTPUT.put_line('触发器日志:要更新的id大于5000.'); ELSE DBMS_OUTPUT.put_line('触发器日志:要更新的id小于5000'); END IF; END; /