8.1 触发器类型
触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了触发ORACLE,如数据库的启动与关闭等。所以触发器常用来完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现审计的功能。
编写触发器时,需要注意以下几点:
- l 触发器不接受参数。
- l 一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
- l 在一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。
- l 触发器最大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。
- l 在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)。
- l 触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。
- l 在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。
- l 在触发器主体中不能申明任何Long和blob变量。新值new和旧值old也不能是表中的任何long和blob列。
- l 不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器)的语法格式和作用有较大区别。
8.2 创建触发器
创建触发器的一般语法是:
CREATE
[OR REPLACE]
TRIGGER
trigger_name
{BEFORE
|
AFTER }
{
INSERT
|
DELETE
|
UPDATE
[OF column [, column …]
]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]
]}...]
ON
[schema.]
table_name
|
[schema.]
view_name
[REFERENCING {OLD [AS]
old
|
NEW
[AS]
new
|
PARENT
as
parent}]
[FOR EACH ROW ]
[WHEN condition] ----只允许在行级触发器上指定触发条件,指定UPDATING后面的列的列表。
PL
/SQL_BLOCK | CALL procedure_name;
其中:
BEFORE 和AFTER指出触发器的触发时序分别为前触发和后触发方式,前触发是在执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建的触发器。
FOR EACH ROW选项说明触发器为行触发器。
行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操作影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则只能为行触发器。
REFERENCING 子句说明相关名称,在行触发器的PL/SQL块和WHEN 子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为OLD和NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。
WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。
当一个基表被修改( INSERT, UPDATE, DELETE)时要执行的存储过程,执行时根据其所依附的基表改动而自动触发,因此与应用程序无关,用数据库触发器可以保证数据的一致性和完整性。
8.2.3 创建替代(INSTEAD OF)触发器
创建触发器的一般语法是:
CREATE
[OR REPLACE]
TRIGGER
trigger_name
INSTEAD
OF
{
INSERT
|
DELETE
|
UPDATE
[OF column [, column …]
]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]
]}...]
ON
[schema.]
view_name
--
只能定义在视图上
[REFERENCING {OLD [AS]
old
|
NEW
[AS]
new
|
PARENT
as
parent}]
[FOR EACH ROW ]
--
因为
INSTEAD OF
触发器只能在行级上触发
,
所以没有必要指定
[WHEN condition]
PL
/SQL_block | CALL procedure_name;
其中:
INSTEAD OF 选项使ORACLE激活触发器,而不执行触发事件。
只能对视图和对象视图建立INSTEAD OF触发器,而不能对表、模式和数据库建立INSTEAD OF 触发器。
FOR EACH ROW选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操走影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则为行触发器。
REFERENCING 子句说明相关名称,在行触发器的PL/SQL块和WHEN 子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为OLD和NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。
WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。
本文转载自:http://blog.csdn.net/indexman/article/details/8023740/