我在一个表a的insert触发器中执行数个update表b c d和insert表e f的操作,当执行表e的insert语句出现主键冲突错误时,后面的代码就不再继续执行了,而且表a中也没有该数据插入,我希望的是如果有一条语句失败触发器不做任何操作而表a中保留该条记录 请问这种问题如何解决?
触发器简单示例代码如下:(表 abcdef的结构忽略 只需知道表e有主键且执行insert的时候会提示主键冲突就可以了)create trigger tr_insert_a on t_a
for insert
as
DECLARE
@errorcode     int    --是否错误select @errorcode=0
SELECT @ROWNUM=@@ROWCOUNTIF @ROWNUM=0
   RETURNbegin tran
if @ROWNUM=1
begin
update b
select @errorcode=@errorcode+@@error
if   @errorcode   <>   0    goto roll

update c
select @errorcode=@errorcode+@@error
update d
select @errorcode=@errorcode+@@error insert e --这条报主键冲突时 好像不会执行rollback
select @errorcode=@errorcode+@@error    insert f
    select @errorcode=@errorcode+@@error
endif @errorcode=0 
commit tran
else
begin
rollback tran
        update g set ggg='fuck' 这条是测试语句 当报错是这条没有执行
end

解决方案 »

  1.   

    create trigger tr_insert_a on t_a
    after insert
    as
      

  2.   

    簡單問題復雜化,2005用begin try begin tran... commit tran end try begin catch.. end catch
      

  3.   

    如果設定 SET XACT_ABORT ONbegin tran
     update b..
     update c..
     ...
    commit tran有錯就一起rollback了
    如果設定SET XACT_ABORT OFF
    就只有發生錯誤的那條語句被rollback
      

  4.   

    问题补充:
    当我把触发器中的update /insert代码拿出来单独执行时 insert e出错后面的insert f也会继续执行
    如:
    (1 行受影响) update b(1 行受影响) update c(1 行受影响) update d
    消息 2627,级别 14,状态 1,第 7 行
    违反了 PRIMARY KEY 约束 'PK_e'。不能在对象 'dbo.t_hjzx_szrx_gd_deal_his' 中插入重复键。
    语句已终止。(1 行受影响) insert f
    但是在触发器中执行,到insert e 的时候就不再往下执行了 提示如下:
    (1 行受影响) update b(1 行受影响) update c(1 行受影响) update d
    消息2627,级别14,状态1,过程tr_insert_a,第54 行
    违反了PRIMARY KEY 约束'PK_e'。不能在对象'dbo.e中插入重复键。
    语句已终止。
    也就是说,后面的rollback什么的都没执行到
      

  5.   

    如果設定 SET XACT_ABORT ONbegin tran
     update b..
     update c..
     ...
    commit tran有錯就一起rollback了
    如果設定SET XACT_ABORT OFF
    就只有發生錯誤的那條語句被rollback
      

  6.   


    try:
    create trigger tr_insert_a on t_a
    for insert
    as
    begin
    DECLARE @errorcode     int    --是否错误
    select @errorcode=0
    SELECT @ROWNUM=@@ROWCOUNT IF @ROWNUM=0
       RETURN begin tran
    set xact_abort  on
    if @ROWNUM=1
    begin
    update b
    select @errorcode=@errorcode+@@error  
        
    update c
    select @errorcode=@errorcode+@@error update d
    select @errorcode=@errorcode+@@error insert e --这条报主键冲突时 好像不会执行rollback
    select @errorcode=@errorcode+@@error insert f
    select @errorcode=@errorcode+@@error
      end
    commit tran
    else
    begin
    rollback tran
    update g set ggg='fuck' 这条是测试语句 当报错是这条没有执行
    end
    end
      

  7.   

    不好意思理解错了
    像楼主说的那样,那这个触发器就没有什么用了
    你直接写一个存储过程就行了呗
    参考:
    create procedure pro_updateA 
    as
    begin DECLARE @errorcode     int,@ROWNUM int    --是否错误
    set @errorcode=0 insert ta values(1,'sadf')
    SELECT @ROWNUM=@@ROWCOUNT IF @ROWNUM = 0 
       RETURN
    IF @ROWNUM <> 1
    update g set ggg='fuck' --这条是测试语句 当报错是这条没有执行
    return begin tran
    set xact_abort  on
    begin
    update b
    set @errorcode=@errorcode+@@error  
        
    update c
    set @errorcode=@errorcode+@@error update d
    set @errorcode=@errorcode+@@error insert e --这条报主键冲突时 好像不会执行rollback
    values(@errorcode+@@error) insert f
    values(@errorcode+@@error)
      end
    commit tranend
      

  8.   

    多谢 使用begin try后可以了 rollback后的update语句也确实执行了 但是表a中还是没有插入的记录
      

  9.   

    已经改成了
    create trigger tr_insert_a on t_a
    after insert
      

  10.   

    create trigger tr_insert_a on t_a 
    after insert
      

  11.   

    設定 SET XACT_ABORT ONbegin tran
     update b..
     update c..
     ...
    commit tran有錯就一起rollback了
    如果設定SET XACT_ABORT OFF
    就只有發生錯誤的那條語句被rollback