ストアドプロシージャの途中で終了するにはどうすればよいですか?
早期に(デバッグを試みながら)救済したいストアドプロシージャがあります。 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]
さらに下のエラーが発生したため、実行し続けます。 printsのいずれも表示されません。ストアドプロシージャの大部分をコメントアウトした場合:
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
質問は次のとおりです。SQLServerのストアドプロシージャをどのように救済するのですか?
RETURN
を使用して、ストアドプロシージャの実行をすぐに停止できます。 Books Online からの引用:
クエリまたはプロシージャから無条件に終了します。 RETURNは即時かつ完全であり、プロシージャ、バッチ、またはステートメントブロックを終了するためにいつでも使用できます。 RETURNに続くステートメントは実行されません。
妄想から、私はあなたの例を試してみましたが、PRINTを出力し、すぐに実行を停止します。
20以上の重大度を指定しない限り、raiserror
は実行を停止しません。 MSDNドキュメント を参照してください。
通常の回避策は、すべてのreturn
の後にraiserror
を含めることです。
if @whoops = 1
begin
raiserror('Whoops!', 18, 1)
return -1
end
TRY/CATCH
。
TISブロックでRAISERRORを重大度11以上で実行すると、関連するCATCHブロックに制御が移ります
参照: [〜#〜] msdn [〜#〜] 。
EDIT:これはMSSQL 2005+で機能しますが、MSSQL 2000で作業していることを明確にしたことがわかります。参照。
RETURN
がストアドプロシージャから無条件に返されない理由を理解しました。私が見ているエラーは、ストアドプロシージャが実行されているときではなく、コンパイル済みであるときに発生します。
架空のストアドプロシージャを考えます。
CREATE PROCEDURE dbo.foo AS
INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure
このstordプロシージャにエラーが含まれている場合でも(オブジェクトの列数が異なるため、テーブルにタイムスタンプ列がある場合、ストアドプロシージャが存在しない場合など)、引き続きsaveそれ。リンクサーバーを参照しているため、保存できます。
ただし、ストアドプロシージャを実際にexecuteすると、SQL Serverはcompilesit 、クエリプランを生成します。
私のエラーは114行目ではhappeningではなく、114行目ではonです。SQL Serverはストアドプロシージャをコンパイルできないため、失敗します。
そして、それがRETURN
が返されない理由です。startedでさえないためです。
これはここで機能します。
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
これは多くのコードのように思えますが、私が見つけた最良の方法です。
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
BEGIN
およびEND
ステートメントがないためです。このステートメントの実行中に印刷物やエラーが表示されることはないはずです。Statement Completed
(またはそのようなもの)。