触发器能做什么?
维护那些通过创建表时的声明约束不可能实现的复杂完整性约束。
通过记录已进行的改变以及是谁进行了该项改变来检查一个表的信息。
当一个表发生改变时,自动向其他程序放送需要采取行动的信号。
在一个发布-预定环境中发布关于各种事件的信息。
触发器的类型:DML触发器、instead-of触发器和系统触发器。
一、DML触发器:
1 ) 由DML语句激发,DML(data manuplating language)——数据操纵语言,包括insert,update,delete。DML触发器总共
可能有12种可能的类型,即3个语句*2个计时*2个级别。3个语句指insert,update和delete,2个计时指在语句执行之前或者
是执行之后激发,2个级别是对于每个受影响的行激发一次还是仅仅对于一个语句激发一次。
2 )一个表可以拥有定义在其上的任意数量的触发器,其中可以包含多个DML触发器。
3) DML触发器的执行顺序:
如果存在,执行语句级别的before触发器;
对于受语句影响的每一行:
如果存在,执行行级别的before触发器;
执行DML语句本身;
如果存在,执行行级别的after触发器;
如果存在,执行语句级别的after触发器;
4 )在行级别触发器中的相关标识符 :old和:new
:old表示当前行的旧值,:new表示当前行的新值。冒号表示它们是绑定变量,PL/SQL编译器把它们当成类型记录
triggering_table%ROWTYPE,引用方式是 :new.field,仅当field是触发表里的字段时,引用才有效。因此,:old和:new也叫做伪记录。
二、instead-of触发器:
顾名思义,instead-of触发器是在企图执行DML语句时激发,但是DML语句将不执行。并且,instead-of触发器只能定义在视图上,
而DML触发器只能定义在表上。instead-of触发器常常用于下面两种情况:当对一个不能修改的视图进行修改时候,常使用它来实现
等价的功能(修改一些表);修改视图中某嵌套表列的列。如果需要执行其他过程,在可更改的视图上也可以编写instead-of触发器。
首先,来区分一下可更改的视图与不可更改的视图。可更改的视图就是一个你可以对其发出DML语句的视图,一般情况下,如果视图
不包括下面的项,就是可更改的:
聚合函数SUM AVG等
GROUP BY等子句
DISTINCT操作符
三、系统触发器:
DML触发器和instead-of触发器都在DML语句事件(insert,update,delete)上触发,系统触发器与它们不同,它在DDL语句事件
或者数据库事件上触发。DDL事件包括:CREATE、ALTER或DROP语句。数据库事件包括服务器启动/关闭、用户登录/注销、以及服务器错误
等。系统触发器的用途在于记录重要的数据库事件。
触发器的例子:
例1 DML触发器
--记录对registered_students表的操作
CREATE OR REPLACE TRIGGER LogRSchanges --LogRSchanges触发器的名字
BEFORE UPDATE ON --可以是or三者中的一种
registerd_students --表名
FOR EACH ROW --行级的
DECLARE
v_changeType CHAR(1);
BEGIN
IF INSERTING THEN
v_changeType :='I';
ELSIF UPDATING THEN
v_changeType :='U';
ELSE
v_changeType :='D';
END IF;
/* 记录信息,USER是当前用户的user id,SYSDATE是当前时间*/
INSERT INTO rs_audit(change_type,changed_by,timestamp,
old_student_id,old_department,
new_student_id,new_department)
VALUES(v_changeType,USER,SYSDATE,
:old.student_id,:old.c,
:new.student_id,:new.department);
END LogRSchanges;
四、使用触发器时,要注意的问题:
1)触发器往往会造成性能瓶颈,因为它以一种side-effect的形式执行,此外,在检查代码性能时,它也容易被忽视。
2)在触发器的实现里,不要做不能会滚的动作,譬如调用UTL_SMTP包来发邮件。因为一旦DML语句会滚,它们将不可撤销,导致不一致的情况发生。
3)不要用触发器来保证实体完整性。
关于触发器的dark corner,Oracle专家Tom的博客里有详细阐述,有兴趣的朋友请看Tom的博客http://writeblog.csdn.net/PostEdit.aspx?entryId=3639888