1:为什么使用触发器
我们设计一个人力资源管理系统时,如果我们遇到这样一个需求,当增加一个员工信息时,也要增加一个该员工信息的薪酬记录,数据库服务器,如Oracle,为我们提供了解决方法,就是触发器,我们不用再去设计监控程序。
触发器是当特定事件出现时自动执行的代码块,比如上面的需求,我们可以创建一个触发器来对员工表的插入、更新和删除操作进行监控,当判断当前时间是礼拜天的时候就禁止这些操作并返回说明
2:触发器的功能
* 允许/限制对表的修改
如限制周末对员工的薪酬进行修改
* 自动生成派生列
* 强制数据一致性
* 强制复杂的完整性约束条件
* 提供审计和日志记录
比如公司的财务表,可以建立一个触发器,随时监控该表的操作,记录哪些用户对该表进行了修改
* 防止无效的事务处理
* 启动复杂的业务逻辑
3:触发器和存储过程的区别
触发器是自动执行的,不能显式的调用
触发器的缺点是性能较低,不适宜过多使用
存储过程是可以显式调用
4:触发器的语法如下图:
5:实例
6:触发器的组成部分
触发器由3个部分组成,触发器语句、触发器限制和触发器操作组成
触发器语句:触发器语句是那些可以导致触发器的事件,即在表或者视图上执行的insert、delete和update之类的DML语句,在模式对象上执行的DDL语句或数据库事件
所有可以导致触发器的事件的都是触发器的语句
如:before insert or update of position
on employees
for each row;
触发器限制:触发器限制条件包含一个布尔表达式,该值必须为"真"才能激活触发器,如果该值为"假"或"未知",将不进行触发操作。
如:when(New.position <> 5)
触发器操作:触发器操作是触发器的主体,包含一些SQL语句和代码,这些代码在执行触发器语句且触发器条件的值为"真"时运行,行级触发器允许触发操作中的语句访问行的列值。
如:begin
: New.manager_id := 2;
end;
7:效果图
执行update employees t set t.position=3 where t.id=29后的结果图如下所示:
8:触发器的类型
触发器分为行级触发器、语句级触发器、INSTEAD OF触发器、模式触发器、数据库触发器
行级触发器和语句级触发器又合称为DML触发器
语句级触发器是指一个DML语句触发一次的触发器
INSTEAD OF触发器主要是在视图上定义的触发器
模式触发器也就是用户事务触发器
数据库级触发器是指创建在数据库事件上的触发器
行级触发器:对DML语句影响的每一次执行一次,例如,update语句影响多行,就会对每行都激活一次行级触发器
行级触发器是触发器中最常见的一种,通常用于数据库审计和实现复杂的业务逻辑,行级触发器可以在
create trigger 命令中指定for each row子句创建行级触发器
由于触发器是事件驱动的,因此可以设置触发器在这些事件之前或者之后执行,即在执行DML语句之前或者之后执行
在DML语句中可以引用旧值和新值,旧值对应old.*,新值对应new.*, “旧”是指在DML语句之前存在的数据,update和delete通常引用旧值
"新"是指由DML语句创建的数据值(如插入记录中的列)。引用的时候使用OLD后面加点或者new后面加点,然后再接字段名
如果需要通过触发器在插入行中设置一个列值,就应该使用BEFORE INSERT触发器访问"新"值,使用after insert触发器不允许设置插入值,因为
该行已经插入表中了。
而在审计应用程序中经常使用after行级触发器,直到行被修改才会触发它们。行的成功修改表明该行已经通过该表定义的完整性约束。
使用行级触发器实现id增加:
create or replace trigger idaddtrig
before insert on idaddt
for each row
begin
select idaddt_sec.nextval into :new.id from dual;
end idaddt_sec;
语句级触发器:对每个DML语句执行一次
例如,如果一条insert语句在表中插入200行,那么这个表上的insert语句级触发器只执行一次。语句级触发器不常用与数据相关的活动,
通常用于强制实施表上执行操作的额外安全性措施。
注意:语句级触发器是create trigger 命令创建的触发器的默认类型
实例:
create or replace trigger trig_idaddt
after insert or update or delete
on idaddt
begin
if updating then
dbms_output.put_line('IDADDT 中的数据已更新');
elsif deleting then
dbms_output.put_line('IDADDT中的数据已删除');
elsif inserting then
dbms_output.put_line('数据已插入 IDADDT');
end if;
end;
也就是在对表IDADDT进行插入、更新或删除操作之后触发此触发器,这个触发器没有触发器限制部分
Oracle条件谓语如下图所示: