トランザクションVSの開始トランザクション(SQL Server)の開始(SQL Server)トランザクションをうまくネストする方法

StackOverflow https://stackoverflow.com//questions/9713350

質問

私はセーブポイントを設定する必要があるストアドプロシージャーを持っています。そのような状況下で、それが行ったものすべてを元に戻し、呼び出し元にエラーコードを返したり、それを受け入れたり、発信者に成功を返すことができるようにする必要があります。しかし、発信者がすでにトランザクションを開始したかどうかをうまく機能させるのが必要です。この主題についてはDOCは非常に混乱しています。これは私が働くものですが、私はすべての影響の一定ではありません。

ものです - このStored Procedure (SP)は他のものによって呼ばれます。だから私は彼らがトランザクションを開始したかどうかわからない...私がユーザーが私のSPを使用するためにトランザクションを起動する必要があるとしても、私はまだSave Pointsの適切な使用に関する質問があります...

マイSPはトランザクションが進行中の場合はテストします。そうでない場合は、BEGIN TRANSACTIONで1つ起動します。トランザクションがすでに進行中の場合は、代わりにSAVE TRANSACTION MySavePointNameで保存ポイントを作成し、これが私がしたことです。

それから私が私の変更をロールバックしなければならない場合は、早くBEGIN TRANSACTIONを実行した場合は、ROLLBACK TRANSACTIONになります。節約ポイントをした場合は、ROLLBACK TRANSACTION MySavePointNameになります。このシナリオは素晴らしい仕事をしているようです。

ここに少し混乱しているところです。しかし、私がセーブポイントを作成した場合COMMIT TRANSACTIONを試しましたが、発信者はそのトランザクションをコミットしてエラーを取得しようとします。

コミットトランザクション要求には対応する開始トランザクションがありません。

だから私は疑問に思う - 保存点をロールバックすることができます(その機能:COMMIT TRANSACTION MySavePointNameは発信者のトランザクションをロールバックしません)。しかし、おそらくそれを「コミット」する必要はありませんか?それはただそこに留まります、あなたがそれにロールバックする必要があるが、元の取引がコミットされたら(またはロールバックされた)かどうかを遅らないでください。

取引を「巣」する方法がある場合は、いくつかの光を当ててください。 ROLLBACK TRANSACTION MySavePointNameでネストする方法を考え出していませんが、LOLLBACKまたは自分の内部取引をコミットするだけです。 BEGIN TRANSACTIONは常にトップトランザクションにロールバックされますが、ROLLBACKは単にCOMMITを減らすだけです。

役に立ちましたか?

解決

私はこれを今すべて出したと信じているので、私は自分の質問に答えます...

http://geekswithblogs.net/bbiales/archive / 03/15/how-to-nest-transactions--- -quotsave - Quotsave。ASPX

だから私のSPはこのようなもので始まり、何もない場合は新しいトランザクションを開始しますが、保存点を使用している場合は保存点を使用してください。

DECLARE @startingTranCount int
SET @startingTranCount = @@TRANCOUNT

IF @startingTranCount > 0
    SAVE TRANSACTION mySavePointName
ELSE
    BEGIN TRANSACTION
-- …
.

その後、変更をコミットする準備ができたら、自分自身の取引を開始した場合にのみコミットする必要があります。

IF @startingTranCount = 0
    COMMIT TRANSACTION
.

そして最後に、これまでのところあなたの変更点だけをロールバックするために:

-- Roll back changes...
IF @startingTranCount > 0
    ROLLBACK TRANSACTION MySavePointName
ELSE
    ROLLBACK TRANSACTION
.

他のヒント

私のストアドプロシージャにこのタイプのトランザクションマネージャを使用しました:

    CREATE PROCEDURE Ardi_Sample_Test  
        @InputCandidateID INT  
    AS  
        DECLARE @TranCounter INT;  
        SET @TranCounter = @@TRANCOUNT;  
        IF @TranCounter > 0  
            SAVE TRANSACTION ProcedureSave;  
        ELSE  
            BEGIN TRANSACTION;  
        BEGIN TRY  

            /*
            <Your Code>
            */

            IF @TranCounter = 0  
                COMMIT TRANSACTION;  
        END TRY  
        BEGIN CATCH  
            IF @TranCounter = 0  
                ROLLBACK TRANSACTION;  
            ELSE  
                IF XACT_STATE() <> -1  
                    ROLLBACK TRANSACTION ProcedureSave;  

            DECLARE @ErrorMessage NVARCHAR(4000);  
            DECLARE @ErrorSeverity INT;  
            DECLARE @ErrorState INT;  
            SELECT @ErrorMessage = ERROR_MESSAGE();  
            SELECT @ErrorSeverity = ERROR_SEVERITY();  
            SELECT @ErrorState = ERROR_STATE();  

            RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);  
        END CATCH  
    GO  
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top