UserInfo(UserID,UserName,DepartID,SerialNum,...)
对于一个部门(DepartID相同)下的用户,我要让其序号SerialNum保持连续,就建立了一个触发器:CREATE OR REPLACE TRIGGER "KSOURCE".TRUSERINFO_INSERT AFTER
INSERT ON "KSOURCE"."USERINFO" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 
Declare 
v_SerialNum Number; 
Begin 
Select Count(*) Into v_SerialNum From UserInfo Where DepartID=:New.DepartID; 
if (:New.SerialNum <> v_SerialNum) Then 
Update UserInfo Set SerialNum=v_SerialNum Where UserID=:New.UserID; 
end if; 
End;这样,如果用户输入的SerialNum不连续了,自动改成连续的,但Insert时却出现如下提示:
表 KSOURCE.USERINFO 发生了变化, 触发器/函数不能读它

解决方案 »

  1.   

    难道Oracle的封锁粒度是整个表,Insert时整个表被锁住了?我建立的可是After触发器啊。如果真的这样,我在删除一个记录时,如删除SerialNum=2的,要把SerialNum>2的都减1,是不是就不能使用触发器了?
      

  2.   

    这里出错原因,估计是行级的触发器代码中不能再操作该表,包括select,默认的在写TRIGGER的时候把本表锁死,不允许对其进行操作,这里可以通过一些AUTONOMOUS_TRANSACTION(自治事务)来解决
    CREATE OR REPLACE TRIGGER "KSOURCE".TRUSERINFO_INSERT AFTER
    INSERT ON "KSOURCE"."USERINFO" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 
    Declare 
    v_SerialNum Number; 
    [font]PRAGMA AUTONOMOUS_TRANSACTION;[/font]
    Begin 
    Select Count(*) Into v_SerialNum From UserInfo Where DepartID=:New.DepartID; 
    if (:New.SerialNum <> v_SerialNum) Then 
    Update UserInfo Set SerialNum=v_SerialNum Where UserID=:New.UserID; 
    end if; 
    End;
    你试试这个解决方式叻,不过对于你这case,确实比较复杂,在你delete一条中间的数据时,确实还要控制其他的serialnum也随之发生变化。这样才能保持连续
    ==================================================================
    Inthirties关注Oracle数据库 维护 优化,安全,备份,恢复,迁移,故障处理如果你需要帮助或想和我一起学习的请联系
    联系方式QQ:370140387
    电子邮件:[email protected]
    网站: http://www.inthirties.com
      

  3.   

    由于是自治形式的,所以在你的程序块里,最后需要加上commit;
    ================================================================== 
    Inthirties关注Oracle数据库 维护 优化,安全,备份,恢复,迁移,故障处理 如果你需要帮助或想和我一起学习的请联系 
    联系方式QQ:370140387 
    电子邮件:[email protected] 
    网站: http://www.inthirties.com 
      

  4.   

    Serial Number 又不是主键, 为什么要它连续呢。 如果真的需要的话, 你可以使用SELECT   ROWNUM       SerialNum
    ,        tbl.COL1
    ,        tbl.COL2
    FROM     ( SELECT *
               FROM   target_table
               ORDER BY  ...
             ) tbl
    ;我觉得你的这个Trigger可能没有必要哦
      

  5.   

    不可跳号的需求很多,比如财务上发票号完全可以序号SerialNum本身自动生成,不用人为干预他。如果还要考虑delete后,所有的序号SerialNum同步刷新,在100w级数据量的时候,系统就没法用了所以,关于delete,前台是不许删除的。打开数据库删除管不了。