首先关于事务的几个操作如下:
begin tran -- 开启事务
commit tran -- 提交事务
rollback tran -- 回滚事务
-- 新建一个测试表demo,id自增
create table demo
(
id int not null IDENTITY(1,1),
val int not null
)
insert into demo values (5)
insert into demo values (2)
select * from demo
set xact_abort on -- 设置当运行发生错误时,整个事务终止并回滚
begin tran -- 开启事务
insert into demo values (5)
insert into demo values (2)
insert into demo values (5)
insert into demo values (null)
insert into demo values (6)
commit tran -- 提交事务
go
当执行到 insert into demo values (null)
这一句时会发生错误,因为设置了 set xact_abort on
,因此所有操作会回滚。
操作结果:
再看一下数据
select * from demo
跟刚刚一样,数据没有增加。
接下来对比一下不设置 xact_abort on
的情况。
set xact_abort off
begin tran -- 开启事务
insert into demo values (5)
insert into demo values (2)
insert into demo values (5)
insert into demo values (null)
insert into demo values (6)
commit tran -- 提交事务
go
数据:
select * from demo
可以看到除了 insert into demo values (null)
这一句,其他数据是有插到数据库的。
注意:
关于事务回滚还有一点,我建的 demo
表的 id
字段是自增的。
看最后的那张图,id=2
的下一条是 id=7
,这说明了其实除了insert into demo values (null)
这一句,其他语句是已经执行了,插入到数据库了的,只是因为遇到错误回滚时又把它们删除了。所以再插入的时候 id
就是从7开始了。
PS:其实不使用 set xact_abort on
也可以手动捕捉错误进行回滚。
这里只是简单介绍一下。
- 在每个单独的DML语句执行后,立即判断执行状态,并做相应处理。
begin transaction
declare @errorSum int --定义局部变量
set @errorSum=0 --初始化临时变量
update bank set currentMoneycurrentMoney= currentMoney-1000 where customerName='张三'
set @errorSum=@errorSum+@@error --累计是否有错误
update bank set currentMoneycurrentMoney= currentMoney+1000 where customerName='李四'
set @errorSum=@errorSum+@@error --累计是否有错误
if @errorSum<>0 --如果有错误
begin
rollback transaction
end
else
begin
commit transaction
end
go
2. 可利用 try…catch 异常处理机制。
begin tran
begin try
update statement 1 ...
delete statement 2 ...
endtry
begin catch
if @@trancount > 0
rollback tran
end catch
if @@trancount > 0
commit tran
go