2011-12-21 16 views
1

午前のSQLジョブで使用される複数のストアドprocsがあり、procsが順番に呼び出されます。 proc内のクエリの1つが失敗した場合、どのクエリが失敗したかを正確に知るために、各クエリに対して行うキャッチ/ロギングエラーが発生します。しかし問題は、これらのプロセスの中には、何かが失敗した場合に開始するのが非常に難しいことがあるため、それぞれのストアドプロシージャにTRANSACTIONを実装することを考えていることです。複数の更新と挿入を伴うSQL Serverトランザクション

現在の手順は、次のようになります。

CREATE PROCEDURE [dbo].[spStep01] 
( 
    @Return_Message  Varchar(1024) OUT  -- Error messages returned to the calling program 
) 
AS 
BEGIN 

SET NOCOUNT ON; 

DECLARE @ErrorCode    int 
DECLARE @ApplicationNumber  int    
DECLARE @TaskNumber    int    
DECLARE @TaskCompleted   smallint   
DECLARE @TaskFailed    smallint   
DECLARE @TaskRunning   smallint   
DECLARE @ErrorSeverity   smallint   
DECLARE @ErrorState    smallint   

SELECT @ErrorCode = @@ERROR 
SELECT @ApplicationNumber = 10     
SELECT @TaskNumber   = 1 
SELECT @TaskCompleted  = 0 
SELECT @TaskFailed   = -1 
SELECT @TaskRunning   = 1 
SELECT @ErrorSeverity  = 16 
SELECT @ErrorState   = 1 

/*************************************************************************** 
* first insert 
***************************************************************************/ 
    BEGIN TRY 
     INSERT INTO ... 
    END TRY 
    BEGIN CATCH 
     SELECT @Return_Message = 'FAILED - first insert did not populate' 
     EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskFailed, @Return_Message  
     RAISERROR (@Return_Message, @ErrorSeverity, @ErrorState) 
     RETURN 
    END CATCH 

/*************************************************************************** 
* second insert 
***************************************************************************/ 
    BEGIN TRY 
     INSERT INTO ... 
    END TRY 
    BEGIN CATCH 
     SELECT @Return_Message = 'FAILED - second insert did not populate' 
     EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskFailed, @Return_Message  
     RAISERROR (@Return_Message, @ErrorSeverity, @ErrorState) 
     RETURN 
    END CATCH 


/*************************************************************************** 
* Procedure has completed successfully 
***************************************************************************/ 
    SELECT @Return_Message = 'SUCCESS - Inserts were complete' 
    EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskCompleted, @Return_Message 


/************************************* 
* Get the Error Message for @@Error 
*************************************/ 
    IF @ErrorCode <> 0 
    BEGIN 
     SELECT @Return_Message = [Description]  -- Return the SQL Server error 
      FROM master.dbo.SYSMESSAGES 
     WHERE error = @ErrorCode 
    END 

/************************************* 
* Return from the Stored Procedure 
*************************************/ 
    RETURN @ErrorCode        -- =0 if success, <>0 if failure 

END 

私は決定しようとしている私は何をTRANSACTIONTRY/CATCHブロックのすべてをラップし、それがすべてをロールバックする場合は、エラーが発生した場合です。私はSOを調べて、examplesのブロックが1つのTRY/CATCHブロックであることを発見しましたが、格納されたprocsのほとんどは複数のブロックを持つことになりました。私はトランザクションに関する多くの経験がないので、この場合正しく実装する方法は100%わかりません。

TRANSACTION作品にラッピングしますか?それとももっと良い方法がありますか?

答えて

5

どのようにこの

BEGIN TRANSACTION tx 
BEGIN TRY 
    @CurrentStep = "First Insert" 
    INSERT ... 

    @CurrentStep = "Second Insert" 
    INSERT ...Second 

    IF @@TRANSCOUNT > 0 
    BEGIN --SUCCESS, nothing failed, now I can commit!! 
    SELECT @Return_Message = 'SUCCESS - Inserts were complete' 
    EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskCompleted, @Return_Message 
    COMMIT TRANSACTION tx; -- now everything is committed 
    END 
END TRY 

BEGIN CATCH 
    IF @@TRANSCOUNT > 0 --something failed 
    BEGIN 
    IF @CurrentStep = 'First Insert' 
     SELECT @Return_Message = 'FAILED - first insert did not populate' 
    ELSE IF @CurrentStep = 'Second Insert' 
     SELECT @Return_Message = 'FAILED - second insert did not populate' 

    EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskFailed, @Return_Message  
    RAISERROR (@Return_Message, @ErrorSeverity, @ErrorState) 

    ROLLBACK TRAN tx; -- everything is rolled back 
    END 
END CATCH 

について希望は、このあなたのためのトリックは、そうでなければ、複数のトランザクションを持つ方がいいでしょう、トランザクション内のすべてがコミットまたはバック一箇所で展開される必要があることを覚えていません。

関連する問題