sql-server – 如何从一个存储过程启动3个存储过程时回滚
>在每个proc的顶部,DECLARE @InBestedTransaction BIT; IF (@@TRANCOUNT = 0) BEGIN SET @InNestedTransaction = 0; BEGIN TRAN; -- only start a transaction if not already in one END; ELSE BEGIN SET @InNestedTransaction = 1; END; >代替简单的COMMIT,执行: IF (@@TRANCOUNT > 0 AND @InNestedTransaction = 0) BEGIN COMMIT; END; >代替简单的ROLLBACK,执行: IF (@@TRANCOUNT > 0 AND @InNestedTransaction = 0) BEGIN ROLLBACK; END; 无论事务是在SQL Server中启动还是在应用层启动,此方法都应该相同. 有关TRY … CATCH结构中此事务处理的完整模板,请参阅以下DBA.SE问题的答案:Are we required to handle Transaction in C# Code as well as in stored procedure. 超越“基础”,还需要注意一些额外的交易细微差别: >默认情况下,大多数情况下,发生错误时,事务不会自动回滚/取消.只要您有适当的错误处理并自己调用ROLLBACK,这通常不是问题.但是,有时事情变得复杂,例如在批量中止错误的情况下,或者在使用OPENQUERY(或一般的链接服务器)时,并且远程系统上发生错误.虽然大多数错误都可以使用TRY … CATCH来捕获,但是有两个错误不能被捕获(不记得当前哪些错误 – 研究).在这些情况下,必须使用SET XACT_ABORT ON才能正确回滚事务. SET XACT_ABORT ON使SQL Server立即回滚任何事务(如果一个处于活动状态)并在发生任何错误时中止批处理.此设置存在于SQL Server 2005之前,它引入了TRY … CATCH构造.在大多数情况下,TRY … CATCH处理大多数情况,因此大多数都废弃了对XACT_ABORT ON的需求.但是,当使用OPENQUERY(可能还有一个我目前不记得的场景)时,您仍然需要使用SET XACT_ABORT ON;. 然而,TRY …… CATCH引入了一个新的“状态”.当不使用TRY … CATCH构造时,如果您有一个活动的事务并且发生错误,那么可以采用几个路径: > XACT_ABORT OFF和语句中止错误:事务仍处于活动状态,并继续处理下一个语句(如果有). 但是,当使用TRY … CATCH时,批量中止错误不会中止批处理,而是将控制转移到CATCH块.当XACT_ABORT为OFF时,交易在绝大多数时间内仍然处于活动状态,您需要COMMIT,或者很可能需要ROLLBACK.但是当遇到某些批量中止错误(例如使用OPENQUERY)或XACT_ABORT为ON时,事务将处于新状态,“不可拒绝”.在这种状态下你不能COMMIT,也不能做任何DML操作.您所能做的就是ROLLBACK和SELECT语句.但是,在这种“不可注册”状态下,事务在发生错误时回滚,并且发出ROLLBACK只是一种形式,但必须完成. 函数XACT_STATE可用于确定事务是处于活动状态,不可控制还是不存在.建议(至少某些人)在CATCH块中检查此功能以确定结果是否为-1(即不可拒绝),而不是测试@@ TRANCOUNT> 0.但是在XACT_ABORT开启的情况下,这应该是唯一可能存在的状态,因此似乎测试@@ TRANCOUNT> 0和XACT_STATE()<> 0是等价的.另一方面,当XACT_ABORT为OFF并且存在活动事务时,则CATCH块中可能具有1或-1的状态,这允许发出COMMIT而不是ROLLBACK(尽管如此,如果事务是可提交的,那么当有人想要COMMIT时,我们就不会想到这种情况.有关在XACT_ABORT ON的CATCH块中使用XACT_STATE()的更多信息和研究可以在我对以下DBA.SE问题的答案中找到:In what cases a transaction can be committed from inside the CATCH block when XACT_ABORT is set to ON?.请注意XACT_STATE()存在一个小错误导致它错误地返回1在某些情况下:XACT_STATE() returns 1 when used in SELECT with some system variables but without FROM clause 关于原始代码的说明: >您可以删除提供给交易的名称,因为它没有任何帮助.>每个EXEC调用都不需要BEGIN和END (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |