Oracle触发器详细介绍

触发器是特定事件出现的时候,自动执行的代码块。类似于存储过程,但是用户不能直接调用他们。

功能:

1、允许/限制对表的修改

2、自动生成派生列,比如自增字段

3、强制数据一致性

4、提供审计和日志记录

5、防止无效的事务处理

6、启用复杂的业务逻辑

开始

createtriggerbiufer_employees_department_id

beforeinsertorupdate

ofdepartment_id

onemployees

referencingoldasold_value

newasnew_value

foreachrow

when(new_value.department_id<>80)

begin

:new_value.commission_pct:=0;

end;

/

触发器的组成部分:

1、触发器名称

2、触发语句

3、触发器限制

4、触发操作

1、触发器名称

createtriggerbiufer_employees_department_id

命名习惯:

biufer(beforeinsertupdateforeachrow)

employees表名

department_id列名

2、触发语句

比如:

表或视图上的dml语句

ddl语句

数据库关闭或启动,startupshutdown等等

beforeinsertorupdate

ofdepartment_id

onemployees

referencingoldasold_value

newasnew_value

foreachrow

说明:

1、无论是否规定了department_id,对employees表进行insert的时候

2、对employees表的department_id列进行update的时候

3、触发器限制

when(new_value.department_id<>80)

限制不是必须的。此例表示如果列department_id不等于80的时候,触发器就会执行。

其中的new_value是代表跟新之后的值。

4、触发操作

是触发器的主体

begin

:new_value.commission_pct:=0;

end;

主体很简单,就是将更新后的commission_pct列置为0

触发:

insertintoemployees(employee_id,

last_name,first_name,hire_date,job_id,email,department_id,salary,commission_pct)

values(12345,’chen’,’donny’,sysdate,12,‘[email protected]’,60,10000,.25);

selectcommission_pctfromemployeeswhereemployee_id=12345;

触发器不会通知用户,便改变了用户的输入值。

触发器类型:

1、语句触发器

2、行触发器

3、insteadof触发器

4、系统条件触发器

5、用户事件触发器

一、语句触发器

是在表上或者某些情况下的视图上执行的特定语句或者语句组上的触发器。能够与insert、update、delete或者组合上进行关联。但是无论使用什么样的组合,各个语句触发器都只会针对指定语句激活一次。比如,无论update多少行,也只会调用一次update语句触发器。

例子:

需要对在表上进行dml操作的用户进行安全检查,看是否具有合适的特权。

createtablefoo(anumber);

createtriggerbiud_foo

beforeinsertorupdateordelete

onfoo

begin

ifusernotin(‘donny’)then

raise_application_error(-20001,‘youdon’thaveaccesstomodifythistable.’);

endif;

end;

/

即使sys,system用户也不能修改foo表

对修改表的时间、人物进行日志记录。

1、建立试验表

createtableemployees_copyasselect*fromhr.employees

2、建立日志表

createtableemployees_log(

whovarchar2(30),

whendate);

3、在employees_copy表上建立语句触发器,在触发器中填充employees_log表。

createorreplacetriggerbiud_employee_copy

beforeinsertorupdateordelete

onemployees_copy

begin

insertintoemployees_log(

who,when)

values(user,sysdate);

end;

/

4、测试

updateemployees_copysetsalary=salary*1.1;

select*fromemployess_log;

5、确定是哪个语句起作用?

即是insert/update/delete中的哪一个触发了触发器?

可以在触发器中使用inserting/updating/deleting条件谓词,作判断:

begin

ifinsertingthen

-----

elsifupdatingthen

-----

elsifdeletingthen

------

endif;

end;

ifupdating(‘col1’)orupdating(‘col2’)then

------

endif;

1、修改日志表

altertableemployees_log

add(actionvarchar2(20));

2、修改触发器,以便记录语句类型。

createorreplacetriggerbiud_employee_copy

beforeinsertorupdateordelete

onemployees_copy

declare

l_actionemployees_log.action%type;

begin

ifinsertingthen

l_action:=’insert’;

elsifupdatingthen

l_action:=’update’;

elsifdeletingthen

l_action:=’delete’;

else

raise_application_error(-20001,’youshouldneverevergetthiserror.’);

insertintoemployees_log(

who,action,when)

values(user,l_action,sysdate);

end;

/

3、测试

insertintoemployees_copy(employee_id,last_name,email,hire_date,job_id)

values(12345,’chen’,’donny@hotmail’,sysdate,12);

select*fromemployees_log

updateemployees_copysetsalary=50000whereemployee_id=12345;

二、行触发器

是指为受到影响的各个行激活的触发器,定义与语句触发器类似,有以下两个例外:

1、定义语句中包含foreachrow子句

2、在before……foreachrow触发器中,用户可以引用受到影响的行值。

比如:

定义:

createtriggerbiufer_employees_department_id

beforeinsertorupdate

ofdepartment_id

onemployees_copy

referencingoldasold_value

newasnew_value

foreachrow

when(new_value.department_id<>80)

begin

:new_value.commission_pct:=0;

end;

/

referencing子句:

执行dml语句之前的值的默认名称是:old,之后的值是:new

insert操作只有:new

delete操作只有:old

update操作两者都有

referencing子句只是将new和old重命名为new_value和old_value,目的是避免混淆。比如操作一个名为new的表时。

作用不很大。

:为主健生成自增序列号

droptablefoo;

createtablefoo(idnumber,datavarchar2(20));

createsequencefoo_seq;

createorreplacetriggerbifer_foo_id_pk

beforeinsertonfoo

foreachrow

begin

selectfoo_seq.nextvalinto:new.idfromdual;

end;

/

insertintofoo(data)values(‘donny’);

insertintofoovalues(5,’chen’);

select*fromfoo;

三、insteadof触发器更新视图

createorreplaceviewcompany_phone_bookas

selectfirst_name||’,’||last_namename,email,phone_number,

employee_idemp_id

fromhr.employees;

尝试更新email和name

updatehr.company_phone_book

setname=’chen1,donny1’

whereemp_id=100

createorreplacetriggerupdate_name_company_phone_book

insteadof

updateonhr.company_phone_book

begin

updatehr.employees

setemployee_id=:new.emp_id,

first_name=substr(:new.name,instr(:new.name,’,’)+2),

last_name=substr(:new.name,1,instr(:new.name,’,’)-1),

phone_number=:new.phone_number,

email=:new.email

whereemployee_id=:old.emp_id;

end;

四、系统事件触发器

系统事件:数据库启动、关闭,服务器错误

createtriggerad_startup

afterstartup

ondatabase

begin

--dosomestuff

end;

/

五、用户事件触发器

用户事件:用户登陆、注销,create/alter/drop/analyze/audit/grant/revoke/rename/truncate/logoff

例子:记录删除对象

1.日志表

createtabledroped_objects(

object_namevarchar2(30),

object_typevarchar2(30),

dropped_ondate);

2.触发器

createorreplacetriggerlog_drop_trigger

beforedropondonny.schema

begin

insertintodroped_objectsvalues(

ora_dict_obj_name,--与触发器相关的函数

ora_dict_obj_type,

sysdate);

end;

/

3.测试

createtabledrop_me(anumber);

createviewdrop_me_viewasselect*fromdrop_me;

dropviewdrop_me_view;

droptabledrop_me;

select*fromdroped_objects

禁用和启用触发器

altertrigger<trigger_name>disable;

altertrigger<trigger_name>enable;

事务处理:

在触发器中,不能使用commit/rollback

因为ddl语句具有隐式的commit,所以也不允许使用

视图:

dba_triggers

http://blog.csdn.net/junmail/article/details/4380213

相关推荐