日期:2014-05-16  浏览次数:20468 次

【转】触发器使用教程和命名规范

触发器使用教程和命名规范???
??
??
目? 录???
触发器使用教程和命名规范??? 1??
1,触发器简介 1??
2,触发器示例 2??
3,触发器语法和功能? 3??
4,例一:行级触发器之一??? 4??
5,例二:行级触发器之二??? 4??
6,例三:INSTEAD OF触发器? 6??
7,例四:语句级触发器之一?? 8??
8,例五:语句级触发器之二?? 9??
9,例六:用包封装触发器代码? 10??
10,触发器命名规范? 11??
??
1,触发器简介???
触发器(Trigger)是数据库对象的一种,编码方式类似存储过程,与某张表(Table)相关联,当有DML语句对表进行操作时,可以引起触发器的执行,达到对插入记录一致性,正确性和规范性控制的目的。在当年C/S时代盛行的时候,由于客户端直接连接数据库,能保证数据库一致性的只有数据库本身,此时主键(Primary Key),外键(Foreign Key),约束(Constraint)和触发器成为必要的控制机制。而触发器的实现比较灵活,可编程性强,自然成为了最流行的控制机制。到了B/S时代,发展成4层架构,客户端不再能直接访问数据库,只有中间件才可以访问数据库。要控制数据库的一致性,既可以在中间件里控制,也可以在数据库端控制。很多的青睐Java的开发者,随之将数据库当成一个黑盒,把大多数的数据控制工作放在了Servlet中执行。这样做,不需要了解太多的数据库知识,也减少了数据库编程的复杂性,但同时增加了Servlet编程的工作量。从架构设计来看,中间件的功能是检查业务正确性和执行业务逻辑,如果把数据的一致性检查放到中间件去做,需要在所有涉及到数据写入的地方进行数据一致性检查。由于数据库访问相对于中间件来说是远程调用,要编写统一的数据一致性检查代码并非易事,一般采用在多个地方的增加类似的检查步骤。一旦一致性检查过程发生调整,势必导致多个地方的修改,不仅增加工作量,而且无法保证每个检查步骤的正确性。触发器的应用,应该放在关键的,多方发起的,高频访问的数据表上,过多使用触发器,会增加数据库负担,降低数据库性能。而放弃使用触发器,则会导致系统架构设计上的问题,影响系统的稳定性。???
??
??
2,触发器示例???
触发器代码类似存储过程,以PL/SQL脚本编写。下面是一个触发器的示例:???
新建员工工资表salary???
create table SALARY???
(???
? EMPLOYEE_ID NUMBER, --员工ID???
? MONTH?????? VARCHAR2(6), --工资月份???
? AMOUNT????? NUMBER --工资金额???
)???
??
创建与salary关联的触发器salary_trg_rai???
1?? Create or replace trigger salary_trg_rai???
2?? After insert on salary???
3?? For each row???
4?? declare???
5?? Begin???
6???? Dbms_output.put_line(‘员工ID:’ || :new.employee_id);???
7???? Dbms_output.put_line(‘工资月份:’ || :new.month);???
8???? Dbms_output.put_line(‘工资:’ || :new.amount);???
9???? Dbms_output.put_line(‘触发器已被执行’);???
10?? End;???
打开一个SQL Window窗口(使用PL/SQL Developer工具),或在sqlplus中输入:???
Insert into salary(employee_id, month, amount) values(1, ‘200606’, 10000);???
执行后可以在sqlplus中,或在SQL Window窗口的Output中见到???
员工ID:1??
工资月份:200606??
工资:10000??
触发器已执行???
??
在代码的第一行,定义了数据库对象的类型是trigger,定义触发器的名称是salary_trg_rai???
第二行说明了这是一个after触发器,在DML操作实施之后执行。紧接着的insert说明了这是一个针对insert操作的触发器,每个对该表进行的insert操作都会执行这个触发器。???
第三行说明了这是一个针对行级的触发器,当插入的记录有n条时,在每一条插入操作时都会执行该触发器,总共执行n次。???
Declare后面跟的是本地变量定义部分,如果没有本地变量定义,此部分可以为空???
Begin和end括起来的代码,是触发器的执行部分,一般会对插入记录进行一致性检查,在本例中打印了插入的记录和“触发器已执行”。???
其中:new对象表示了插入的记录,可以通过:new.column_name来引用记录的每个字段值???
??
??
3,触发器语法和功能???
触发器的语法如下???
CREATE OR REPLACE TRIGGER trigger_name???
<before | after | instead of> <insert | update | delete> ON table_name???
[FOR EACH ROW]???
WHEN (condition)???
DECLARE???
BEGIN???
??? --触发器代码???
END;???
??
Trigger_name是触发器的名称。<before | after | instead of>可以选择before或者after或instead of。Before表示在DML语句实施前执行触发器,而after表示在在dml语句实施之后执行触发器,
instead of触发器用在对视图的更新上。<insert | update | delete>可以选择一个或多个DML语句,如果选择多个,则用or分开,如:insert or update。Table_name是触发器关联的表名。???
[FOR EACH ROW]为可选项,如果注明了FOR EACH ROW,则说明了该触发器是一个行级的触发器,DML语句处理每条记录都会执行触发器;否则是一个语句级的触发器,每个DML语句触发一次。???
WHEN后跟的condition是触发器的响应条件,只对行级触发器有效,当操作的记录满足condition时,触发器才被执行,否则不执行
。Condition中可以通过new对象和old对象(注意区别于前面的:new和:old,在代码中引用需要加上冒号)来引用操作的记录。???
触发器代码可以包括三种类型:未涉及数据库事务代码,
涉及关联表(上文语法中的table_name)数据库事务代码,涉及除关联表之外数据库事务代码。其中第一种类型代码只对数据进行简单运算和判断,没有DML语句,这种类型代码可以在所有的触发器中执行。