我写了一个触发器,如:
create or replace trigger Trig_BeforeUpdate_smgp
  Before  UPDATE ON smscom.smgp_mt_hn
  for each row
declare
  
begin
  IF :new.status <> -1 
  THEN 
 --将已返回状态报告的数据放入历史表,同时在接口表中删除
       Insert Into smscom.His_Smgp_Mt_Hn 
             ( Msg_Id, Report_Id, Innerfee_Id, Src_Number, Dest_Number, Msg_Content, Link_Id, sys_time,status) 
       values( :old.msg_id, :old.Report_Id,:old.Innerfee_Id, 
             :old.Src_Number, :old.Dest_Number, :old.Msg_Content, :old.link_id, :old.sys_time,:new.status);      
         Delete From smscom.Smgp_Mt_Hn Where Msg_Id = :old.msg_id;
  END IF;
end Trig_BeforeUpdate_smgp;我能创建成功,但是在运行的时候,是报不可读的错误,是我级联触发器和动态表相冲突。后来我改了,把中间的Delete From smscom.Smgp_Mt_Hn Where Msg_Id = :old.msg_id;的删除语句给去掉了,能运行了,但是我的功能却么蜜语实现,我应该怎么样做才能实现我原来的功能呢。我希望他将数据放入历史表的同时在原来的表中删除。这改怎么实现呢?
麻烦各位高手帮帮忙~~~~~

解决方案 »

  1.   

    begin前面加
    pragma autonomous_transaction;
      

  2.   


    我用了,还是报同样的错误:代码是:
    create or replace trigger Trig_BeforeUpdate_smgp
      Before  UPDATE ON smscom.smgp_mt_hn
      for each row
    declare
      pragma autonomous_transaction;
    begin  IF :new.status <> -1 
      THEN 
     --将已返回状态报告的数据放入历史表,同时在接口表中删除
           Insert Into smscom.His_Smgp_Mt_Hn 
                 ( Msg_Id, Report_Id, Innerfee_Id, Src_Number, Dest_Number, Msg_Content, Link_Id, sys_time,status) 
           values( :old.msg_id, :old.Report_Id,:old.Innerfee_Id, 
                 :old.Src_Number, :old.Dest_Number, :old.Msg_Content, :old.link_id, :old.sys_time,:new.status);      
             Delete From smscom.Smgp_Mt_Hn Where Msg_Id = :old.msg_id;
      END IF;
      
      commit;
    end Trig_BeforeUpdate_smgp;
      

  3.   

    Before  改为after呢?你这里删了,后面又去update,那怎么update得到么
      

  4.   

    测了,不行。我不知道了。sorry
      

  5.   

    看上去有点像电信短信项目。我原来是用存储过程来做的。
    update如果是这种需要马上转移的数据,则不update了,直接把数据select 出来insert到另一个表里面,然后删除这个表的对应数据。否则的话就执行update
      

  6.   


    我改了,照样报同样的错误,改为after了
      

  7.   


    是的,这是电信的短信项目,你上面说的那种方法,我试过了,也不行啊:
         --将已返回状态报告的数据放入历史表,同时在接口表中删除
           Insert Into smscom.His_Smgp_Mt_Hn 
                 ( Msg_Id, Report_Id, Innerfee_Id, Src_Number, Dest_Number, Msg_Content, Link_Id, sys_time,status) 
           Select msg_id, Report_Id,Innerfee_Id, 
                 Src_Number, Dest_Number, Msg_Content, link_id, sys_time,status
           From smscom.Smgp_Mt_Hn Where Msg_Id = :old.msg_id; 

           Delete From smscom.Smgp_Mt_Hn Where Msg_Id = :old.msg_id;我本来是这么写,后来报不可读的错误。才改了的。
      

  8.   

    我的意思是,我不是用trigger的,我是用存储过程来完成整个逻辑的。
      

  9.   

       你没有声明变量,无需使用declare。
       去掉declare, 再试试看!
      

  10.   

    首先,你第一个报不可读的错误,是trigger中访问到你的变异表,也就是说,你基于smgp_mt_hn表创建的trigger,在trigger体中你又进行了对smgp_mt_hn表的操作,Oracle规定:不能访问变异表!其次,自治事务来解决你的第一个问题,是正确的,自治事务不会受主事务的影响,自动提交。但是接踵而来的问题,你也遇到了,也就是dead lock。原因是,自治事务访问到你外层事务未提交的数据,因为主事务必须等待自治事务提交之后才恢复,就像你程序中一样,如果主事务执行update 操作,此时主事务未提交,但是此时却触发了你的update trigger,而你trigger体中又在进行基表的操作,最终导致了死锁。当Oracle检查到dead lock之后,会自动rollback你的自治事务。最后,解决办法:最好用存储过程去实现。
    还有,对于你的业务需求,你创建的trigger 是UPDATE smscom.smgp_mt_hn ,最后又要delete,你试想下逻辑合理不?当我执行一条update操作,不仅没有update,反而却delete更改的记录,虽然你要的需求是这样的,但是不合乎常理。
      

  11.   

    变通下利用view的instead of触发器
    [TEST@ora10gr1] SQL>desc test01;
     名称                                      是否为空? 类型
     ----------------------------------------- -------- ----------------------------
     ID                                                 NUMBER(38)[TEST@ora10gr1] SQL>desc test01;
     名称                                      是否为空? 类型
     ----------------------------------------- -------- ----------------------------
     ID                                                 NUMBER(38)[TEST@ora10gr1] SQL>select * from test01;        ID
    ----------
             1[TEST@ora10gr1] SQL>select * from test02;未选定行[TEST@ora10gr1] SQL>create or replace view test01_view as select * from test01;视图已创建。[TEST@ora10gr1] SQL>create or replace trigger test01_view_trigger instead of update on test01_view
      2  begin
      3  insert into test02 select * from test01_view where id=:old.id;
      4  delete from test01_view where id=:old.id;
      5  end;
      6  /触发器已创建[TEST@ora10gr1] SQL>update test01_view set id=2;已更新 1 行。[TEST@ora10gr1] SQL>select * from test01;未选定行[TEST@ora10gr1] SQL>select * from test02;        ID
    ----------
             1[TEST@ora10gr1] SQL>