web-dev-qa-db-ja.com

ループ内のTRY / CATCH内のRAISERRORの動作

SQLのセクションで、期待どおりに動作しないことがあります(問題のパターンを示す問題のSQLの蒸留バージョンについては、以下を参照してください)。

(これはSQL Server 2008 R2 SP2 64ビット上にあります)

'do some work here'の部分でエラーが発生し、CATCHブロックでエラー処理がトリガーされます。エラー番号は515(null不可の列にnullを挿入しようとする)であるため、RAISERRORはエラーを報告しますが、ループは続行し、作業を再試行し、無限ループでエラーなどをスローします。

RAISERRORによって実行がループを終了することを期待します。ここで何が起こっているのですか?

ありがとう

WHILE (@Applied <> 1)
BEGIN

    BEGIN TRY

        -- === Do some work here ===

        -- Successfully applied
        SET @Applied = 1;

    END TRY
    BEGIN CATCH

        -- Save the error details
        SELECT
            @ErrorNumber = ERROR_NUMBER(),
            @ErrorMessage = ERROR_MESSAGE(), 
            @ErrorSeverity = ERROR_SEVERITY(), 
            @ErrorState = ERROR_STATE();

        -- Test for a deadlock or uncommittable transaction
        IF (@ErrorNumber = 1205 OR @ErrorNumber = 3930)
            -- Sleep for 5 seconds
            WAITFOR DELAY '00:00:05';
        ELSE
            RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);

    END CATCH
END
1
redcalx

RAISERRORは通常、実行を停止しません。 [〜#〜] throw [〜#〜] はそうですが、SQL 2012で導入されました。

RETURN;またはRETURN -1;の後のRAISERROR

以下は、MSDNページの [〜#〜] raiserror [〜#〜] の「備考」セクションからの抜粋です。

TRYブロックで重大度が11以上のRAISERRORが実行されると、関連するCATCHブロックに制御が移ります。 RAISERRORを実行すると、エラーが呼び出し元に返されます。

  • TRYブロックの範囲外。
  • TRYブロックの重大度が10以下。
  • データベース接続を終了する重大度20以上。

以下は、動作の簡単なテストです。 2012より前のバージョンのSQL Serverで実行している場合は、コメントアウトするか、THROWの行を削除してください。

RAISERROR(N'This is from RAISERROR - Severity 16', 16, 1);
PRINT N'----- 1';

;THROW 50505, N'This is from THROW', 1;
PRINT N'----- 2';

GO

PRINT N'----- 3';

-- WITH LOG needed for severity > 18
RAISERROR(N'This is from RAISERROR - Severity 20', 20, 1) WITH LOG;
PRINT N'----- 4';

GO

PRINT N'----- 5';

上記のテストでは、[メッセージ]タブで次のものが返されます。

メッセージ50000、レベル16、状態1、行2
これはRAISERROR-重大度16からです
----- 1
メッセージ50505、レベル16、状態1、行5
これはTHROWからのものです
----- 3
メッセージ2745、レベル16、状態2、行4
プロセスID 54でユーザーエラー50000、重大度20が発生しました。SQLServerがこのプロセスを終了しています。
メッセージ50000、レベル20、状態1、行4
これはRAISERRORの重大度20です
メッセージ0、レベル20、状態0、行0
現在のコマンドで重大なエラーが発生しました。結果がある場合は、破棄する必要があります。

また、SSMSの左下隅には「切断」と表示されます。

5
Solomon Rutzky