1 前言 当然,在触发器修改自身数据表,对于有Oracle数据库后台编程人员来说,并不应该算是一个难题,可能在平时的工作中就经常要碰到。 但对于刚刚使用ORACLE数据库后台编程人员来说,的确是一个比较烦人的问题。
2 说明 ORACLE的触发器分为两类:行触发器(For Each Row)和表触发器,在行触发器中,不得将Insert/Update/Delete语句作用于自身数据表;在表触发器中,不得使用:New/:Old语句。 但在实际编程过程中,我们往往需要对自身数据表进行DML(Insert/Update/Delete)操作,同时引用:New/:Old对象。 如:使用Insert Into xxx (Select * From yyy Where xKey=123456)语句后,我们需要保存插入记录的时间,由于数据库操作的时间差,我们不可以使用:New.xDate:=SysDate语句<使用这一语句后,插入的每笔记录xDate的数值会不一样,可相差数秒>。 对我们来说,最好的语句是:Update xxx Set xDate=SysDate Where xKey=:New.xKey。此时,我们使用Update语句的同时,又使用了:New对象,ORACLE认为不合法。 3 解决提案 实现此需求,我们需要建立一个行触发器、一个表触发器以及一个程序包。 --3.0 创建测试环境 Drop Table xxx; Drop Table yyy; --创建数据表 Create Table xxx( xKey Number(4), xDate Date, xData number(10)); Create Table yyy( xKey Number(4), xDate Date, xData number(10)); --3.1 创建程序包,设立全局变量G_xKe Create Or Replace Package Pkg_xxx_Update as G_xKey xxx.xKey%Type; End Pkg_xxx_Update; / --3.2 创建行触发器,并将xKey的值存入程序包的全局变量中 Create Or Replace Trigger TRG_Upd_xxx_Rec After Insert On xxx For Each Row Begin Pkg_xxx_update.G_xKey:=:New.xKey; End; / --3.3 创建表触发器,根据程序包的全局变量,对数据表的xDate字段进行更新 Create Or Replace Trigger TRG_Upd_xxx_TB After Insert On xxx Begin Update xxx set xDate=SysDate Where xKey=PKG_xxx_Update.G_xKey; End; / --3.4 插入大量数据 <<InsertMultiRecord>> Declare L_Count Number:=1; Begin Delete from yyy; While L_Count<100000 Loop insert into yyy values(1, SysDate, L_Count); L_Count:=L_Count+1; End Loop; Commit; End InsertMultiRecord; --3.5 测试触发器 Insert Into xxx (Select * from yyy); Commit; Select * From xxx;
|