加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql-server – 如何从一个存储过程启动3个存储过程时回滚

发布时间:2021-01-14 09:15:39 所属栏目:编程 来源:网络整理
导读:我有一个存储过程,只在其中执行3个存储过程.如果主SP成功,我只使用1个参数来存储. 如果第一个存储过程在主存储过程中正常工作,但第二个存储过程失败,那么它会自动回滚主SP中的所有SP还是我必须做一些命令? 这是我的程序: CREATE PROCEDURE [dbo].[spSavesom

>在每个proc的顶部,DECLARE @InBestedTransaction BIT;
>代替简单的BEGIN TRAN,执行:

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;.
>在触发器内部,XACT_ABORT隐式设置为ON.这会导致触发器中的任何错误取消触发触发器的整个DML语句.
>您应始终进行适当的错误处理,尤其是在使用事务时. SQL Server 2005中引入的TRY … CATCH构造提供了一种处理几乎所有情况的方法,这是在每个语句之后对@@ ERROR进行测试的一种受欢迎的改进,这对批量中止错误没有多大帮助.

然而,TRY …… CATCH引入了一个新的“状态”.当不使用TRY … CATCH构造时,如果您有一个活动的事务并且发生错误,那么可以采用几个路径:

> XACT_ABORT OFF和语句中止错误:事务仍处于活动状态,并继续处理下一个语句(如果有).
> XACT_ABORT OFF和大多数批量中止错误:事务处于活动状态,处理将继续进行下一批处理(如果有).
> XACT_ABORT OFF和某些批量中止错误:回滚事务并继续处理下一批(如果有).
> XACT_ABORT ON和任何错误:回滚事务并继续处理下一批(如果有).

但是,当使用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

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读