web-dev-qa-db-ja.com

SQL Server-TRY / CATCHが特定の状況で機能しない

everyexpected *の場合にCATCHコードブロックを呼び出す保護されたコードをどのように記述できますか(動的にすべてをラップするようなファンキーなジャンクを行わずに) SQL)?

たとえば、これは機能しません。

  1. ステップのないSQLエージェントジョブを定義する
  2. TRY/CATCH内でジョブを開始してみてください

    BEGIN TRY
        EXEC msdb.dbo.sp_start_job @job_name = 'my_empty_job'
    END TRY
    BEGIN CATCH
        SELECT [MyError] = 'Error caught: ' + ISNULL(ERROR_MESSAGE(), 'NULL')
    END CATCH
    

メッセージ22022、レベル16、状態1、行0 SQLServerAgentエラー:ジョブmy_empty_job(ユーザーxyzから)の実行要求は、ジョブにジョブステップがないため拒否されました。

エラーの重大度は16であるため、CATCHブロックをバイパスしないでください。 wtf?!?

また、ジョブがリクエストの処理でビジー状態の場合は、CATCHブロックをバイパスします(テストで停止リクエストと開始リクエストをスパム送信しています)。

メッセージ22022、レベル16、状態1、行0 SQLServerAgentエラー:ジョブmy_simple_job(ユーザーxyzから)を実行する要求は、ジョブがユーザーxyzからの保留中の要求を既に持っているため拒否されました。

関連ケース: 無効なリンクサーバー参照

追伸ジョブの呼び出しを処理するための狭い範囲のソリューションが必要だと思い込まないでください。将来再利用できる汎用的なソリューションを探しています。

P.P.S.存在しないジョブ(「指定された@job_name( 'missing_job')が存在しません。」)を起動・停止しようとした場合をキャッチできます。なぜそれは違う振る舞いをするのですか?

*TRY/CATCHが処理しないもの (tl; dr範囲外の重大度(10, 20)

6
Elaskanator

予想されるすべてのケースでCATCHコードブロックを呼び出す保護されたコードをどのように記述できますか(動的SQLですべてをラップするようなファンキージャンクを実行せずに)?

残念ながらできません。

SQL Server MVP Erland Sommarskogには、SQL Serverでのエラー処理に関する一連の簡単な*記事があり、ここから始まります: SQL Serverでのエラーとトランザクション処理

エージェントジョブで実行している問題は、拡張ストアドプロシージャを呼び出すことです。これによりエラーが発生します。特に、そのエラーはmaster.dbo.xp_sqlagent_notify

Erlandはその問題をカバーしています ここ

SQL Serverにはまだかなりの数の拡張ストアドプロシージャが付属しており、そのうちのいくつかは文書化されており、他はSQL Serverに付属するツールのみを対象としています。エラー処理に関して、すべての賭けはこれらの人たちとは関係ありません。一貫した動作はなく、ほぼすべてのXPには独自のひねりがあります。

広く適用されない興味のあるオーダーメイドのソリューションに興味がないと言ったと思いますが、Microsoftが出荷するストアドプロシージャを扱う場合、このTRY/CATCHの問題に対する1つの解決策は、常にリターンコードをキャプチャすることです。手順の。ゼロ以外の場合は、手動でエラーを発生させてCATCHブロックをトリガーできます( Dan Guzman に感謝)。

*簡単です、はあ!

10
Josh Darnell