日期:2014-05-17  浏览次数:20565 次

set xact_abort on 回滚问题
本帖最后由 drsheldoncooper 于 2013-03-22 23:31:10 编辑
MSSQL2008,运行2段代码:
运行1:

create table a (x char(10),y int)
go
create trigger [dbo].[a_limit] on [dbo].[a]
for insert
as
if exists(select 1 from inserted where y>0)
  raiserror('错误',16,1)
go
set xact_abort on
begin tran
insert into a values('001',1)
insert into a values('002',2)
commit tran
go
--------结果---------
x               y
001        1
002        2

运行2:

create table a (x char(10),y int)
go
create trigger [dbo].[a_limit] on [dbo].[a]
instead of insert
as
if exists(select 1 from inserted where y>1)
  raiserror('错误',16,1)
go
set xact_abort on
insert into a values('001',1)
insert into a values('002',2)
go
--------结果---------
x               y


问题1:set xact_abort on是否一定要跟begin tran/***/commit tran才能回滚?
问题2:运行1的表a加了for触发器,插入操作加了事务,2句插入语句都抛出错误,为什么事务没有回滚?
问题3:运行2的表a加了instead of触发器,插入操作没有加事务,第2句插入语句抛出错误,为什么第1条插入语句也回滚了?
问题4:set xact_abort on/begin tran/***/commit tran和begin tran/try***/catch***/commit tran有什么区别?

------解决方案--------------------
问题1:是的,xact_abor只是个选项,要配合显示事务才有效果
问题2:你定义的错误只能被try catch捕获处理,不能引发tran的回滚,就如你定义的只是个提示,并没有真正意义上事务的错误
问题3:如2所说,其实并没有引发回滚,而是你定义的instead of触发器代替了insert操作,只给出了一个提示
问题4:加上try catch的话就可以处理你定义的那种错误提示了,可以转到catch语句块中进行显示rollback操作
------解决方案--------------------
引用:
 set xact_abort on就是隐式事务,指从此开始一个事务,一值到整个提交结束都是一个事务。不需要begin tran,两个一起使用,相当与事务嵌套,没有意义。

请不要误导


create table a (x char(3),y int)

set xact_abort on
insert into a values('001',1)
insert into a values('0032',2)
insert into a values('003',3)
set xact_abort off
go
select * from a

/*
(1 行受影响)
消息 8152,级别 16,状态 14,第 11 行
将截断字符串或二进制数据。

(1 行受影响)

x y
001 1
*/




set xact_abort on
begin tran
insert into a values('001',1)
insert into a values('0032',2)
insert into a values('003',3)
commit
set xact_abort off
go
select * from a

(1 行受影响)
消息 8152,级别 16,状态 14,第 12 行
将截断字符串或二进制数据。

(0 行受影响)

x y
----------

------解决方案--------------------
额,弄错了,,抱歉,这个试开启隐式回滚
而非隐式事务,谢谢的szm341,看来我对set xact_abort on的理解看来有严重错误,多谢指导。
具体范例MSDN上有详细例子

而你的问题回答就应该这样

问题1:set xact_abort on是否一定要跟begin tran/***/commit tran才能回滚?
begin tran。。 commit tra