1. 什么是触发器
在Oracle中,触发器是一种特殊的存储过程,它在发生某种数据库事件时由Oracle系统自动触发。触发器通常用于加强数据的完整性约束和业务规则等,
对于表来说,触发器可以实现比CHECK约束更为复杂的约束。
触发器与存储过程的区别:
存储过程是由用户或应用程序显式调用的,而触发器是不能被直接调用的,而是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。
2. 触发器的功能
1. 允许/限制对表的修改
2. 自动生成派生列,比如自增字段
3. 强制数据一致性
4. 提供审计和日志记录
5. 防止无效的事务处理
6. 启用复杂的业务逻辑
3. 触发器的优缺点
3.1 优点
触发器可通过数据库中的相关表实现级联更改,不过,通过级联引用完整性约束可以更有效地执行这些更改。
触发器可以强制比用CHECK 约束定义的约束更为复杂的约束。与CHECK 约束不同,触发器可以引用其它表中的列。
例如,触发器可以使用另一个表中的SELECT 查询结果插入或更新的数据,以及执行其它操作,如修改数据或显示用户定义错误信息。
触发器也可以评估数据修改前后的表状态,并根据其差异采取对策。
一个表中的多个同类触发器(INSERT、UPDATE 或DELETE)允许采取多个不同的对策以响应同一个DML语句。
3.2 缺点
触发器功能强大,轻松可靠地实现许多复杂的功能,但是如果滥用触发器会造成数据库及应用程序的维护困难。
在数据库操作中,我们可以通过关系、触发器、存储过程、应用程序等来实现数据操作。
同时规则、约束、缺省值也是保证数据完整性的重要保障。如果我们对触发器过分的依赖,势必影响数据库的结构,
同时增加了维护的复杂性,同时使用触发器也会降低数据库的性能。
4. 触发器的组成
1. 触发事件:引起触发器被触发的事件。
例如:DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、
DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、
数据库系统事件(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。
2. 触发时间:即该触发器是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也就是触发事件和该触发器的操作顺序。
3. 触发操作:即该触发器被触发之后的目标是什么,正是触发器本身要做的事情。
4. 触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,触发器才会执行触发操作。
5. 触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发操作。
6. 触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
5. 触发器的应用
1.确保数据库的安全性;可以基于时间限制用户的操作,例如不允许下班后和节假日修改数据库数据。
可以基于数据库中的数据限制用户的操作,例如不允许价格的升幅一次超过10%。
2.实施复杂的安全性授权;利用触发器控制实体的安全性。
3.提供复杂的审计功能;审计用户操作数据库的语句,如:把用户对数据库的更新写入审计表。
4.维护不同数据库之间同步表;在不同的数据库之间可以利用快照来实现数据的复制,但有些系统要求两个数据库数据实时同步,
就必须利用触发器从一个数据库中向另一个数据库复制数据。
5.实现复杂的数据完整性规则;实现非标准的数据完整性检查和约束。触发器可产生比规则更为复杂的限制。
与规则不同,触发器可以引用列或数据库对象。提供可变的缺省值。
6. 编写触发器的注意事项
1. 触发器不接受参数。
2. 一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
3. 在一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。
4. 触发器最大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。
5. 在触发器的执行部分只能用DQL语句(SELECT)和DML语句(INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)。
6. 触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。
7. 在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。
8. 在触发器主体中不能声明任何Long和blob变量。新值new和旧值old也不能指向表中的任何long和blob列。
9. 不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器和DDL 触发器)的语法格式和作用有较大区别。
10. 触犯器声明变量赋值方式使用:= 符号来赋值。新值new, 旧值old前面不要忘记:符号。
7. 遇到的问题及解决办法
在学习触发器的时候,有这么一条命令:
DBMS_OUTPUT.put_line('已添加一条记录');
但是,触发器被触发后,根本看不到哪里输出了这条语句,后来在网上找到了原因,需要执行一条命令:
set serverout on;
执行这条命令之后,就可以看到输出了。
参考网址:http://hi.baidu.com/no20win/item/2b83d09e01b1b43e336eebac