我在一个表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
触发器简单示例代码如下:(表 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
after insert
as
update b..
update c..
...
commit tran有錯就一起rollback了
如果設定SET XACT_ABORT OFF
就只有發生錯誤的那條語句被rollback
当我把触发器中的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什么的都没执行到
update b..
update c..
...
commit tran有錯就一起rollback了
如果設定SET XACT_ABORT OFF
就只有發生錯誤的那條語句被rollback
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
像楼主说的那样,那这个触发器就没有什么用了
你直接写一个存储过程就行了呗
参考:
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
create trigger tr_insert_a on t_a
after insert
after insert
update b..
update c..
...
commit tran有錯就一起rollback了
如果設定SET XACT_ABORT OFF
就只有發生錯誤的那條語句被rollback