日期:2014-05-17 浏览次数:20848 次
--分析:
ALTER PROC up_test3
AS
PRINT 'begin'
BEGIN TRAN
COMMIT TRAN
PRINT 'end'
go
ALTER PROC up_test2
AS
ROLLBACK --#3.注意:一个嵌套存储过程中的任何一个rollback语句,都会回滚到最顶级的父的begin tran,这儿的例子就是#1步的BEGIN TRAN
--RAISERROR('',16,1)
GO
ALTER PROC up_test1
AS
BEGIN TRAN --#1.显示开启一个事务
EXEC up_test2 --#2.调用子存储过程(相当于你的触发器)
PRINT '^_^' --#4.注意,这时候。SQL并不会在#3步就终止执行,还是会继续往下走
EXEC up_test3 --#5.调用up_test3,正常调用.
SELECT @@trancount
COMMIT --#6.当执行到这儿时,所有ROLLBACK之前的BEGIN TRAN都已经被ROLLBACK撤销了.所以就没有与这个COMMIT对应的BEGIN TRAN了,所以就报错
GO
EXEC UP_TEST1
/*
消息 266,级别 16,状态 2,过程 up_test2,第 0 行
EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。
^_^
begin
end
消息 3902,级别 16,状态 1,过程 up_test1,第 7 行
COMMIT TRANSACTION 请求没有对应的 BEGIN TRANSACTION。
*/
--解决方案:
--1、rollback 后边带 begin tran,有可能破坏业务逻辑。这个方法,其实是可行的,楼主为什么说它会破坏业务逻辑呢?
--2、不用rollback等,用raiserror发送错误码,在调用它的语句里控制事务。 这个方法也可行,就是要注意在最外层一定要有异常捕获,捕获后,再统一ROLLBACK.既然已经是2005,个人推荐使用这种方法。
BEGIN TRY
BEGIN TRAN
EXEC UP_TEST1
COMMIT TRAN
END try
begin CATCH
rollback
END catch
--3、先判断一下@@tran,如果有事务就不再加这些语句。 这个我没理解什么意思。