SQLスクリプトの実行を中断する方法


16

私はSQLスクリプトに取り組んでおり、いくつかの条件が満たされない場合、スクリプトの継続を停止する必要があります。

GoogleでGoogleを検索したところ、重大度が20のRaisErrorが終了することがわかりました。しかし、いくつかの理由で、私はそのオプションを使用できません。

SQLスクリプトの実行を停止する可能な代替手段を教えてください。


1
エラーの発生が許容できないのはなぜですか?また、このスクリプトはストアドプロシージャですか?
ナンフィビアン

私はあなたの最初の質問を明確に理解していませんでした。2番目の質問。いいえ、これはSPではありません
新しい開発者

1
スクリプトとは何ですか?複数のバッチで構成されていますか?ここで答えを見ましたか?
マーティンスミス

回答:


8

RAISERRORのドキュメント(強調鉱山):

0〜18の重大度レベルは、どのユーザーでも指定できます。19〜25の重大度レベルは、sysadmin固定サーバーロールのメンバーまたはALTER TRACE権限を持つユーザーのみが指定できます。重大度レベルが19〜25の場合、WITH LOGオプションが必要です。

スクリプトを実行しているプリンシパルがこれらの基準を満たしていない可能性が高いです。

を使用しても何も問題はありませんRAISERROR。過度の重大度レベルを使用しているだけです。発生したエラーのデフォルトとしてレベル16を使用すると、シーケンスが終了します。より正確にしたい場合は、Microsoftが提供するレベルに従うことができます。

ここに画像の説明を入力してください

さて、スクリプトのコンテキストによっては、RAISERRORそれだけではスクリプトを「終了」しないため、(通常の重大度レベルを使用して)を使用するだけでは不十分な場合があります。

例えば:

RAISERROR(N'Test', 16, 1);

SELECT 1;   /* Executed! */

これはされます、両方のエラーが発生し、結果セットを返します。

スクリプトをすぐに終了するには、使用することをお勧めしますRETURNGOTO-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方法を使用できます。



6

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)にジャンプしました。


7
単一のバッチがある場合にのみ機能し、GOステートメントを取得するとすぐに壊れます。
ガブリエル


0

に同意しますがSET NOEXEC ON/OFF、ストアドプロシージャ(単一のブロックを含む)では、単にRETURNステートメントを使用します。

警告:スクリプトファイルでは、複数のGOステートメントがある場合RETURN、現在のブロックからのみ出て、次のブロック/バッチに進みます。

注:GOTOコーディングは不適切であると想定TRY..CATCHされています。SQLServer 2008以降に導入されTHROW、2012 年に導入されたため、「」の使用をお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.