The road to C# master trapemiya

C#を中心に、.NETの話題を取り上げます。

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  256  : 記事  1  : コメント  10763  : トラックバック  30

ニュース

Since 2005年10月26日

わんくま同盟

わんくま同盟

Microsoft MVP


Visual Developer - Visual C#

記事カテゴリ

書庫

日記カテゴリ

2008年3月13日 #

ストアドプロシージャ内で普通にTRY...CATCHを使用するとそこでエラーを握りつぶしてしまい、呼び出し元アプリケーションにエラーがあったことが伝わらない。
例えば以下のように書くとエラーを握りつぶしてしまう。

BEGIN TRY 
   BEGIN TRANSACTION
 
   --なんとかかんとか
 
      COMMIT TRANSACTION
END TRY
BEGIN CATCH
   ROLLBACK TRANSACTION
END CATCH

この対処方法がBooks Onlineに載っている。

Transact-SQL での TRY...CATCH の使用
http://msdn2.microsoft.com/ja-jp/library/ms179296.aspx

「TRY...CATCH での RAISERROR の指定」に書かれている。
それによると、CATCHで捕まえた後、RAISERRORを利用してエラーを再スローしなきゃいけないようだ。
で、再スローするためのストアドプロシージャの例が載っている。これを以下に引用する。

CREATE PROCEDURE usp_RethrowError AS
    -- Return if there is no error information to retrieve.
    IF ERROR_NUMBER() IS NULL
        RETURN;

    DECLARE
        @ErrorMessage    NVARCHAR(4000),
        @ErrorNumber     INT,
        @ErrorSeverity   INT,
        @ErrorState      INT,
        @ErrorLine       INT,
        @ErrorProcedure  NVARCHAR(200);

    -- Assign variables to error-handling functions that
    -- capture information for RAISERROR.
    SELECT
        @ErrorNumber = ERROR_NUMBER(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE(),
        @ErrorLine = ERROR_LINE(),
        @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

    -- Building the message string that will contain original
    -- error information.
    SELECT @ErrorMessage =
        N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' +
            'Message: '+ ERROR_MESSAGE();

    -- Raise an error: msg_str parameter of RAISERROR will contain
    -- the original error information.
    RAISERROR
        (
        @ErrorMessage,
        @ErrorSeverity,
        1,              
        @ErrorNumber,    -- parameter: original error number.
        @ErrorSeverity,  -- parameter: original error severity.
        @ErrorState,     -- parameter: original error state.
        @ErrorProcedure, -- parameter: original error procedure name.
        @ErrorLine       -- parameter: original error line number.
        );

で、これを利用して以下のようにすると、ストアドプロシージャの呼び出し元アプリケーションにめでたくエラーが伝わる。

BEGIN TRY 
    BEGIN TRANSACTION
 
   --なんとかかんとか
 
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION
 
    -- Call the procedure to raise the original error.
    EXEC usp_RethrowError; 
END CATCH

で、ここで疑問なのが、なぜusp_RethrowErrorなんていうストアドプロシージャをわざわざ作らなきゃならないのだろう?
最初からRETHROWERRORなんていうステートメントを用意しといてくれたらいいのに。

posted @ 16:11 | Feedback (673)