私はSQLスクリプトに取り組んでおり、いくつかの条件が満たされない場合、スクリプトの継続を停止する必要があります。
GoogleでGoogleを検索したところ、重大度が20のRaisErrorが終了することがわかりました。しかし、いくつかの理由で、私はそのオプションを使用できません。
SQLスクリプトの実行を停止する可能な代替手段を教えてください。
私はSQLスクリプトに取り組んでおり、いくつかの条件が満たされない場合、スクリプトの継続を停止する必要があります。
GoogleでGoogleを検索したところ、重大度が20のRaisErrorが終了することがわかりました。しかし、いくつかの理由で、私はそのオプションを使用できません。
SQLスクリプトの実行を停止する可能な代替手段を教えてください。
回答:
RAISERRORのドキュメント(強調鉱山):
0〜18の重大度レベルは、どのユーザーでも指定できます。19〜25の重大度レベルは、sysadmin固定サーバーロールのメンバーまたはALTER TRACE権限を持つユーザーのみが指定できます。重大度レベルが19〜25の場合、WITH LOGオプションが必要です。
スクリプトを実行しているプリンシパルがこれらの基準を満たしていない可能性が高いです。
を使用しても何も問題はありませんRAISERROR
。過度の重大度レベルを使用しているだけです。発生したエラーのデフォルトとしてレベル16を使用すると、シーケンスが終了します。より正確にしたい場合は、Microsoftが提供するレベルに従うことができます。
さて、スクリプトのコンテキストによっては、RAISERROR
それだけではスクリプトを「終了」しないため、(通常の重大度レベルを使用して)を使用するだけでは不十分な場合があります。
例えば:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
これはされます、両方のエラーが発生し、結果セットを返します。
スクリプトをすぐに終了するには、使用することをお勧めしますRETURN
(GOTO
-typeコンストラクトの使用は、代替案が存在するほとんどのプログラミングサークルでは一般的に推奨されません)。
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
またはTRY/CATCH
、を使用してエラーを処理します。これによりCATCH
、重大度が11以上の場合、実行がブロックにジャンプします。
BEGIN TRY
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Not executed */
END TRY
BEGIN CATCH
SELECT 2; /* Executed */
END CATCH
BEGIN TRY
RAISERROR(N'Test', 10, 1);
SELECT 1; /* Executed */
END TRY
BEGIN CATCH
SELECT 2; /* Not executed */
END CATCH
別の問題は、スクリプトは、複数のバッチにまたがるされている場合- RETURN
にのみ終了するバッチ:
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
SELECT 2; /* Executed! */
これを修正するに@@ERROR
は、すべてのバッチの開始時に確認できます。
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
RETURN;
SELECT 2; /* Not executed */
編集:Martin Smithがコメントで正しく指摘しているように、これは2つのバッチに対してのみ機能します。3つ以上のバッチに拡張するには、次のようにエラーを発生させてカスケードできます(注:GOTO
バッチ内でターゲットラベルを定義する必要があるため、メソッドはこの問題を解決しません)。
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 2; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 3; /* Not executed */
また、彼が指摘しているように、環境に適している場合はこのSQLCMD
方法を使用できます。
GOTO
ステートメントを利用して、必要な場所をスキップできます。つまり、エラーまたは他の何らかの条件に遭遇した場合、スクリプトの下部にラベルを付けて(つまりTheEndOfTheScript:
)、goto TheEndOfTheScript;
ステートメントを発行するだけです。
以下に簡単なサンプルを示します。
print 'here is the first statement...';
print 'here is the second statement...';
-- substitute whatever conditional flow determining factor
-- you'd like here. I have chosen a dummy statement that will
-- always return true
--
if (1 = 1)
goto TheEndOfTheScript;
print 'here is the third statement...';
print 'here is the fourth statement...';
TheEndOfTheScript:
print 'here is the end of the script...';
この実行の出力は次のようになります。
here is the first statement...
here is the second statement...
here is the end of the script...
ご覧のとおりGOTO
、3番目と4番目のステートメントの印刷をスキップし、ラベル(TheEndOfTheScript
)にジャンプしました。
最良の方法は、SET NOEXEC ONを使用することです
詳細については、SQL Serverの特定の条件に基づいて、GOステートメントで区切られた現在のバッチおよび後続のバッチのステートメントの実行を停止または中止または中断する方法を参照してください。