触发器是特定事件出现的时候,自动执行的代码块。类似于存储过程,触发器与存储过程的区别在于:存储过程是由用户或应用程序显式调用的,而触发器是不能被直接调用的。
功能:
1、 允许/限制对表的修改
2、 自动生成派生列,比如自增字段
3、 强制数据一致性
4、 提供审计和日志记录
5、 防止无效的事务处理
6、 启用复杂的业务逻辑
触发器触发时间有两种:after和before。
1、触发器的语法:
CREATE [OR REPLACE] TIGGER触发器名 触发时间 触发事件
ON表名
[FOR EACH ROW]
BEGIN
pl/sql语句
END
其中:
触发器名:触发器对象的名称。
由于触发器是数据库自动执行的,因此该名称只是一个名称,没有实质的用途。
触发时间:指明触发器何时执行,该值可取:
before---表示在数据库动作之前触发器执行;
after---表示在数据库动作之后出发器执行。
触发事件:指明哪些数据库动作会触发此触发器:
insert:数据库插入会触发此触发器;
update:数据库修改会触发此触发器;
delete:数据库删除会触发此触发器。
表 名:数据库触发器所在的表。
for each row:对表的每一行触发器执行一次。如果没有这一选项,则只对整个表执行一次。
1.例子
由于项目中支付单(jd_zfdh_info)关联的支付单详细费用表(jd_fyyb_detail),支付单审批登记表(spd_print),支付单审批工作流工作项表(wfworkitem),工作项意见表(wfauditing)之间没有使用外键关联,如果删除了一条支付单信息记录,其他表的数据还是存在,为了删除这些没用的多余数据,我就用了一个触发器去实现。
触发其代码:
create or replace trigger LM_JD_ZFDH_INFO before delete on jd_zfdh_info
for each row
declare
-- v_row jd_zfdh_info%rowtype;
spdid int;
begin
--v_row:=:old;
--v_row.zfdh_id:=:old.zfdh.id;
--上两行注释是因为报错了,注释掉不要了
select processid into spdid from spd_print where zhdh=:old.zfdh_id;
--查询出支付登记表中的流程实例ID赋值给spdid,说明一下一个支付单只对应一个支付登记,一个审批流程实例
delete from spd_print where zhdh=:old.zfdh_id;
--删除支付单对应的支付登记表中的信息,如果没有对应的支付登记信息也执行
delete from jd_fyyb_detail where rela_zfdh_id=:old.zfdh_id;
--删除支付单对应的详细支付项信息
IF spdid!=null THEN --如果流程实例ID不为空
declare
cursor workitemids is select workitemid from wfworkitem where processinstid=spdid;
--oracle中游标有点像java中的迭代器,拿过来就用了,也没详细去了解
item wfworkitem.workitemid%type;--定义一个工作项id变量
begin
open workitemids;--打开游标
loop--开始迭代
exit when workitemids %notfound;--当游标不存在时,直接结束游标循环;exit语句必须出现在循环中
fetch workitemids into item;--从游标中抓取一个值放进变量item
delete from wfauditing where workitemid=item;--执行删除工作项对应的审批意见
end loop;--结束循环
close workitemids;--关闭游标
delete from wfworkitem where processinstid=spdid;--删除流程实例对应的工作项
end;
end IF;--结束if判断
end LM_JD_ZFDH_INFO;--结束触发器
总结:
数据库为我们提供了丰富的功能齐全的工具,经常使用他们可以解决很多问题,做web的时候,把这些删除数据的任务让服务器去处理还不知道花费多少性能,况且我使用的平台式soa的面向构件开发,这些删除功能做下来使用很多的构件。在数据库端做维护比起构件业务开发,大大降低了出错的概率。