【发布时间】:2011-08-09 05:52:24
【问题描述】:
我的问题:是否可以从 SQL Server 2005 中的另一个存储过程回滚一个存储过程?
我有 SP1 将值插入一个表和 SP2 将值插入另一个表。 因此,如果在执行 SP2 时出现任何错误,我也想回滚 SP1。
请任何人帮助我解决我的问题。
谢谢, 巴拉特
【问题讨论】:
标签: sql-server rollback
我的问题:是否可以从 SQL Server 2005 中的另一个存储过程回滚一个存储过程?
我有 SP1 将值插入一个表和 SP2 将值插入另一个表。 因此,如果在执行 SP2 时出现任何错误,我也想回滚 SP1。
请任何人帮助我解决我的问题。
谢谢, 巴拉特
【问题讨论】:
标签: sql-server rollback
您需要将两个调用包装在一个事务中。
如果您在 SQL 中调用它们,那么这就是方式,或者使用更全面的版本,例如 7 分钟前 gbn 回答的其他答案。
create proc doall as
BEGIN TRY
BEGIN TRAN
EXECUTE SP1
EXECUTE SP1
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH;
如果您从其他来源调用 SP,例如从非 SQL 程序,您需要使用 Microsoft 分布式事务协调器 (MSDTC) 服务设置外部事务。
根据您使用的 API,您可以在代码中设置事务,然后根据条件在代码中提交和回滚。
例如在 .net 中,您可以使用 System.Transactions 命名空间来创建分布式事务。
在主程序中
var tran = new System.Transactions.Transaction();
.
.
.
in one piece of code doe a db call (and pass the tran object to the sql connection) so it enlists in the transaction... if it fails - abort the transaction (trans.Rollback())
.
.
.
.
in another piece of code do another db call (and pass the tran object to the sql connection) so it enlists in the transaction... if it fails - abort the transaction (trans.Rollback())
.
.
.
later...
if both pieces of code succeed commit the transaction
This 是对 this 命名空间的一个很好的介绍,如果您使用的是 .net
【讨论】:
您需要一个包装存储过程来管理事务。
进入和退出存储过程的@@TRANCOUNT 必须相同,否则会出现错误 266。例如,在启动 TXN 后,您无法退出 SP1。
我假设 SP1 和 SP2 可以独立调用,因此您需要一个嵌套事务。 然后你遇到了同样的错误,因为
所以你仍然可以得到错误 266。
我的回答在这里解释了更多关于它的信息,包括嵌套、错误 266 抑制等:Nested stored procedures containing TRY CATCH ROLLBACK pattern?
所以在你的情况下,你需要这样的东西
CREATE PROCEDURE Wrapper
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT
IF @starttrancount = 0
BEGIN TRANSACTION
EXEC SP1
EXEC SP2
IF @starttrancount = 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO
【讨论】: