关于触发器修改自身数据表实例

2/9/2008来源:Oracle教程人气:6168


  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;