ストアドプロシージャに出力パラメーターを設定しようとしていますが、トランザクションをロールバックすると、割り当てを@out
にもロールバックしていると思います。あれは正しいですか?
もしそうなら、どうすればメッセージを返し、トランザクションをロールバックできますか? C#から@out
パラメータをフェッチしています。
create PROCEDURE [dbo].[sp]
@out varchar(2000) output
AS
BEGIN
SET NOCOUNT ON
BEGIN TRANSACTION
BEGIN TRY
SET @OUT = "success";
COMMIT TRANSACTION
END TRY
BEGIN CATCH
set @out = 'not success';
ROLLBACK TRANSACTION
END CATCH
END
私はもともとやっていた
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
...しかし、それは助けにはなりませんでしたが、私はその方法を好みます。
このストアドプロシージャを作成するより堅牢な方法は次のとおりです。
CREATE PROCEDURE dbo.sp
AS
BEGIN
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
SELECT 1/0; -- An error!
/* Other good code omitted*/
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
DECLARE @Message nvarchar(2048) = ERROR_MESSAGE();
DECLARE @Severity integer = ERROR_SEVERITY();
DECLARE @State integer = ERROR_STATE();
RAISERROR(@Message, @Severity, @State);
RETURN -1;
END CATCH;
END;
XACT_ABORT
の使用と、BEGIN TRY
の前の結果には注意してください。また、RAISERROR
は、以下のリファレンスで説明されている理由により、しばしばTHROW
よりも preferred よりも重要です。
RAISERRORとは異なり、; THROWは常にバッチを中止します。
バッチを中止すると、出力パラメーター 割り当てられていない になります。
SQL Serverでのエラー処理は極端に風変わりなので、Erland Sommarskogによるこのトピックに関する独創的な作業を確認することをお勧めします: SQL Serverでのエラーとトランザクションの処理 。
SQL Server 2016を使用しているため、 THROW
を使用することをお勧めします
これにより、TRY
構文がCATCH
構文に迂回する原因となったエラーが発生し、同じエラーが再度スローされます。
ここで必要な場合は、エラーをテーブルに記録したり、ROLLBACK
が実行しないクリーンアップ演習を行ったりすることもできます。
明確に言うと、呼び出し側のアプリケーションにとって、これは例外であり、結果セットではありません。
注:THROW
mustの前のステートメントはセミコロンで終了する必要があります。そうでない場合は、たとえば次のように解釈されます。 ROLLBACK TRANSACTION THROW
トランザクション名またはセーブポイント名としてTHROW
を使用します。