您的位置:首页 > 数据库 > Oracle

Oracle中触发器(1)

2015-08-06 16:01 423 查看
Oracle数据库触发器是存储于数据库的命名PL/SQL语句块,当触发事件发生时他们会隐含的执行,执行触发器的活动被称为触发触发器。特定用户在特定模式下,或者任何用户执行的ddl语句(如create或者alter),这种触发器经常被用于审计目的,并且专用于oracle DBA。可以记录各种模式修改,何时执行、以及那个用户执行的。
系统事件,如数据库启动或者关闭
用户事件,如登录或者注销。即可以定义一个触发器,在用户登录数据库时记录用户名和登录时间。
触发器相关视图:
创建触发器的通用语法:
create [or replace] trigger trigger_name
{before|after} triggering_event on table_name
[for each row]
[follows another_trigger]
[enable/disable]
[when condition]
declare
declaration statements
exception
exception-bandling statements
end ;
triggering_event 是针对数据库表的dml语句,table_name是与该触发器相关的数据库表的名称,子句for each row指定行触发器,只适用于所插入、修改或者删除的数行。when子句指定执行触发器时必须要满足的条件。 触发器的这部分称为触发器的头。

子句follows、enable、disable,它们是在oracle 11g的create or replace trigger
子句中加入的。在11之前需要使用alter trigger 命令来启用或者禁用触发器。

enable/disable子句指定触发器是在启用,还是禁用状态下被创建的。当触发器
被启用时,触发事件发生就会执行该触发器,类似的,当触发器被禁用时,触发
事件发生时也不会执行该触发器。
注意在默认情况下,不使用enable/disable子句创建触发器时,默认是启用的。
alter trigger trigger_name disable ;
alter trigger trigger_name enable ;


使用follows选项,可以指定触发器被触发的顺序,这个选项适用于在相同表上所定义的,并且在相同时间点会执行的触发器。例如,如果在student表上定义两个触发器,并且在数据插入之前触发,如果自己不使用follows子句来指定执行顺序,oracle无法保证这些触发器始终按照相同的次序执行,注意,follows子句中所引用的触发器必须已经存在,并且编译成功。
注意:如果删除一个表,则在该表上所定义的数据库触发器也会被删除。

触发器可以被用于不同的目的:
1.执行不能通过使用完整性约束来定义的复杂业务规则
2.维护复杂的安全规则
3.自动生成衍生列的值
4.手机有关访问数据库表的统计信息
5.防止无效的事务
6.提供值审计

触发器的限制
1.触发器也许不会执行事务控制语句,例如commit、savepoint、rollback。当
触发器执行时,所有执行的操作会成为事务的一部分。当该事务被提交或者回滚
,触发器所执行的操作也会被提交或者回滚。这个规则的一个例外是包含自治事
务的触发器。
2.触发器调用的任何函数或者过程也许不会执行事务控制语句,除非包含自治事务
3.不允许在触发器体中声明long或者long raw变量

触发器的分类:before触发器和after触发器
before触发器
create or replace trigger student_bi
before insert on student
for each row
declare
v_student_id student.student_in%type ;
begin
select student_id_seq.nextval
into v_student_id
from dual ;
:new.student_id := v_student_id ;
:new.created_by := user ;
:new.created_date := sysdate ;
:new.modified_by := user ;
:new.mocified_date := sysdate ;
end ;
触发器包含伪记录:new,使得可以访问当前正在被处理的数据行,也就是说当前被插入student表的数据行。:new伪记录是一种triggering_table%type,所以在在当前情况下,它是student%type类型,为了访问伪记录:new的单独成员,需要使用点符号,也就是:new.created_by指的是:new伪记录的成员created_by,记录名和其成员之间使用点符号。
把序列值赋予student_id列的语句,通过pl/sql表达式访问序列是11G的新特性
在11G之前,只能通过查询访问序列。

如下情况,应该使用before触发器
1.当在insert或者update语句完成之前,触发器需要提供衍生列的值是。
如,enrollment表中final_grade列保存学生特定课程的最终成绩,这个值
来自于学生在整个课程期间的综合表现
2.当触发器决定insert、update或者delete语句是否应该允许完成的时候,如
当往instructor表插入一条记录,触发器可以验证给zip列提供的值是否有效,
或者也就是说,zipcode中是否存在对应整个值的记录

AFTER触发器
一个statistics表的结构如下所示
Name					   Null?    Type
----------------------------------------- -------- ----------------------------
TABLE_NAME					    VARCHAR2(30)
TRANSACTION_NAME				    VARCHAR2(10)
TRANSACTION_USER				    VARCHAR2(30)
TRANSACTION_DATE				    DATE


整个表用来收集数据库中不同表的统计信息,例如,可以记录谁从instractor表删除记录,以及删除的时间。
create or replace trigger instructor_aud
after update or delete on instructor
declare
v_type varchar2(10);

begin
if updating then
v_type := 'UPDATE';

elsif deleting then
v_type := 'DELETE';
end if;

update statistics
set transaction_user = user, transaction_date = sysdate
where table_name = 'instructor'
and transaction_name = v_type;

if sql%notfound%type then
insert into statistics values ('instructor', v_type, user, sysdate);
end if;

end;
例子针对表instructor,触发器会在表update或者delete语句执行之后触发。

如下情况,应该使用after触发器
1.当触发器应该在dml语句执行之后被触发时。
2.当触发器执行before触发器中未指明的动作时。

触发器类型
行级触发器和语句级触发器
instead of触发器

行级触发器指的是触发器被触发的次数等同于触发语句所影响的数据行数量。当
语句for each row出现在create trigger中时,该触发器就是行级触发器。

语句级触发器
没执行一次,触发器就会执行一次,不管触发语句影响多少数据行

详细操作见下篇.....

本文出自 “相守姑娘说” 博客,请务必保留此出处http://sugarlovecxq.blog.51cto.com/6707742/1682287
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: