需要澄清事务SQL SERVER

时间:2013-09-27 06:15:08

标签: sql-server transactions

我读了这个Stackoverflow问题 Nested stored procedures containing TRY CATCH ROLLBACK pattern?

我需要澄清交易模板 gbn 已经回答的问题。 我无法评论并在那里问。

CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT

    IF @starttrancount = 0
        BEGIN TRANSACTION

       [...Perform work, call nested procedures...]

    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

我的问题是!

为什么要使用?

  

SELECT @starttrancount = @@ TRANCOUNT,而不是直接使用@@ TRANCOUNT?

以及为什么要检查这个?

  

IF @starttrancount = 0          开始交易

     

IF @starttrancount = 0         提交交易

我是交易的新手,用例子解释会非常有帮助。 谢谢:))

1 个答案:

答案 0 :(得分:0)

IF @starttrancount = 0 BEGIN TRANSACTION

IF @starttrancount = 0 COMMIT TRANSACTION

使用它们是因为@starttrancount保证只允许最外层存储过程使用事务,因此只存在一个事务。

示例:我们要执行最外层的过程,然后该事务必须仅在最外层的过程中使用。

外部存储过程

CREATE PROCEDURE sp_outer
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT -- Initially @@TRANSCOUNT =0

    IF @starttrancount = 0
        BEGIN TRANSACTION     -- @@TRANSCOUNT =1

       EXEC sp_inner  -- Inner Procedure is called with @@TRANSCOUNT =1 
                      -- so that Transaction in inner procedure will not be used. 
                      -- Per Transaction is exists.

    IF @starttrancount = 0 
        COMMIT TRANSACTION    -- @@TRANSCOUNT = 0
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION  -- If Error occurs Rollback takes place.
    RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO

2.Inner存储过程

CREATE PROCEDURE sp_inner
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT  -- @@TRANCOUNT =1

    IF @starttrancount = 0 
        BEGIN TRANSACTION   -- Skipped

       [...Perform work, call nested procedures...]

    IF @starttrancount = 0 
        COMMIT TRANSACTION  -- Skipped
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION -- if Error Caught Roll back does not happen here
    RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc] -- Error thrown to outer stored procedure.
END CATCH
GO

  

为什么SELECT @starttrancount = @@ TRANCOUNT,而不是使用   @@ TRANCOUNT直接??

由于@@ TRANSCOUNT范围存在于两个存储过程中,用于维护过程范围内的值 使用@starttrancount变量。