【问题标题】:Need Clarification on Transaction SQL SERVER需要澄清事务 SQL SERVER
【发布时间】:2013-10-03 08:16:05
【问题描述】:

我阅读了这个 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??

为什么要检查这个?

如果@starttrancount = 0 开始交易

如果@starttrancount = 0 提交交易

我是 transaction 新手,举例说明会很有帮助。 谢谢:)

【问题讨论】:

    标签: sql-server transactions


    【解决方案1】:
    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.内部存储过程

    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
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-09
      • 2012-07-18
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 2012-06-02
      相关资源
      最近更新 更多