72

ストアド プロシージャの途中で終了するにはどうすればよいですか?

早期に (デバッグ中に) 救済したいストアド プロシージャがあります。RETURNとを呼び出してみましたがRAISERROR、sp は引き続き実行されます。

CREATE PROCEDURE dbo.Archive_Session @SessionGUID uniqueidentifier AS

    print 'before raiserror'
    raiserror('this is a raised error', 18, 1)
    print 'before return'
    return -1
    print 'after return'

[snip]

さらに下でエラーが発生したため、実行し続けていることがわかります。印刷物が表示されません。ストアド プロシージャの大部分をコメント アウトすると、次のようになります。

CREATE PROCEDURE dbo.Archive_Session @SessionGUID uniqueidentifier AS

    print 'before raiserror'
    raiserror('this is a raised error', 18, 1)
    print 'before return'
    return -1
    print 'after return'

   /*
     [snip]
   */

その後、エラーが発生せず、結果が表示されます。

before raiserror
Server: Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 5
this is a raised error
before return

問題は、SQL Server のストアド プロシージャから抜け出すにはどうすればよいかということです。

4

7 に答える 7

95

RETURNストアド プロシージャの実行をすぐに停止するために使用できます。Books Onlineからの引用:

クエリまたはプロシージャを無条件に終了します。RETURN は即時かつ完全であり、プロシージャ、バッチ、またはステートメント ブロックを終了するためにいつでも使用できます。RETURN に続くステートメントは実行されません。

パラノイアから、私はあなたの例を試してみました.PRINTを出力し、すぐに実行を停止します.

于 2009-12-07T21:13:16.763 に答える
30

20 以上の重大度を指定しない限り、raiserror実行は停止しません。MSDN のドキュメントを参照してください。

通常の回避策はreturnafter everyを含めることraiserrorです:

if @whoops = 1
    begin
    raiserror('Whoops!', 18, 1)
    return -1
    end
于 2009-12-07T21:10:29.000 に答える
12

に入れTRY/CATCHます。

TRY ブロックで 11 以上の重大度で RAISERROR が実行されると、関連付けられた CATCH ブロックに制御が転送されます。

参照: MSDN .

編集: これは MSSQL 2005+ で機能しますが、MSSQL 2000 で作業していることを明確にしたようです。参照用にここに残します。

于 2009-12-07T21:10:07.940 に答える
9

RETURNがストアド プロシージャから無条件に返されない理由がわかりました。私が見ているエラーは、ストアドプロシージャが実行されているときではなく、コンパイルされているときです。

架空のストアド プロシージャを考えてみましょう。

CREATE PROCEDURE dbo.foo AS

INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure

このストアド プロシージャにエラーが含まれていても (オブジェクトの列数が異なるため、テーブルにタイムスタンプ列が存在するため、ストアド プロシージャが存在しない可能性があります)、それでも保存できます。リンク サーバーを参照しているため、保存できます。

しかし、ストアド プロシージャを実際に実行すると、SQL Server はそれをコンパイルし、クエリ プランを生成します。

私のエラーは114 行目ではなく、114行目です。SQL Server はストアド プロシージャをコンパイルできないため、失敗しています。

まだ始まっRETURNていないので、それが戻ってこない理由です。

于 2009-12-07T21:37:09.467 に答える
4

これはここで動作します。

ALTER PROCEDURE dbo.Archive_Session
    @SessionGUID int
AS 
    BEGIN
        SET NOCOUNT ON
        PRINT 'before raiserror'
        RAISERROR('this is a raised error', 18, 1)
        IF @@Error != 0 
            RETURN
        PRINT 'before return'
        RETURN -1
        PRINT 'after return'
    END
go

EXECUTE dbo.Archive_Session @SessionGUID = 1

戻り値

before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error
于 2009-12-07T21:27:43.523 に答える
4

これは多くのコードのように思えますが、私が見つけた最良の方法です。

    ALTER PROCEDURE Procedure
    AS

    BEGIN TRY
        EXEC AnotherProcedure
    END TRY
    BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT 
            @ErrorMessage = ERROR_MESSAGE(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorState = ERROR_STATE();

        RAISERROR (@ErrorMessage, -- Message text.
                   @ErrorSeverity, -- Severity.
                   @ErrorState -- State.
                   );
        RETURN --this forces it out
    END CATCH

--Stuff here that you do not want to execute if the above failed.    

    END --end procedure
于 2012-09-24T19:58:43.883 に答える
1

BEGINandENDステートメントがないためです。プリントや、このステートメントの実行中のエラーStatement Completed(またはそのようなもの) のみが表示されることはありません。

于 2009-12-07T22:00:34.093 に答える