私は5つの異なる内部プロシージャを呼び出すような外部プロシージャを持っています
Parent procedure(Tran/try/catch)
Inner sp1 (Tran/try/catch)
'
'
Inner sp5 (Tran/try/catch)
ただし、この場合、内部プロシージャの1つがロールバックされても、外部プロシージャにはエラーがないため、プロシージャはコミットされます。この問題を解決するにはどうすればよいですか?ありがとう!!
すみません。コードは次のようになります。--INNER PROCEDURE
CREATE PROC spInner
AS
BEGIN
DECLARE @transactioncount INT
SET @transactioncount = @@TRANCOUNT
IF (@transactioncount > 0)
BEGIN
SAVE TRANSACTION savepoint1
END
ELSE
BEGIN
BEGIN TRANSACTION
BEGIN TRY
DROP TABLE IF EXISTS #temp
CREATE TABLE #temp (id INT NOT NULL)
INSERT INTO #temp (id)
SELECT NULL
INSERT INTO #temp (id)
SELECT 1
INSERT INTO #temp (id)
SELECT 'A'
IF (@transactioncount = 0)
BEGIN
COMMIT TRANSACTION
END
END TRY
BEGIN CATCH
IF (@transactioncount = 0)
BEGIN
ROLLBACK TRANSACTION
END
ELSE IF (XACT_STATE() <> -1)
BEGIN
ROLLBACK TRANSACTION savepoint1
END
--logs errors into Error Log table
PRINT ERROR_MESSAGE()
END CATCH
END
-外側の手順
CREATE PROC spOuter
AS
BEGIN
DECLARE @transactioncount INT
SET @transactioncount = @@TRANCOUNT
IF (@transactioncount > 0)
BEGIN
SAVE TRANSACTION savepoint2
END
ELSE
BEGIN
BEGIN TRANSACTION
BEGIN TRY
Exec dbo.spInner
IF (@transactioncount = 0)
BEGIN
COMMIT TRANSACTION
END
END TRY
BEGIN CATCH
IF (@transactioncount = 0)
BEGIN
ROLLBACK TRANSACTION
END
ELSE IF (XACT_STATE() <> -1)
BEGIN
ROLLBACK TRANSACTION savepoint2
END
--logs errors into Error Log table
PRINT ERROR_MESSAGE()
END CATCH
END
この場合、内部プロシージャでエラーが発生しても、内部プロシージャでキャッチされたエラーは外部プロシージャではキャッチされず、外部プロシージャがコミットされます。
あなたが直面している問題は、TRY ... CATCHコンストラクトがエラーを処理する方法にあります-エラーを消費し、食べて、戻りコード0以外は何も吐き出しません。これは docs on TRY ... CATCH の非常に無害な行で示されています
CATCHブロックによってトラップされたエラーは、呼び出し元のアプリケーションには返されません。エラー情報の一部をアプリケーションに返す必要がある場合、CATCHブロックのコードは、SELECT結果セットやRAISERRORおよびPRINTステートメントなどのメカニズムを使用して返す必要があります。
ただし、この行は古くなっているようで、THROWステートメントに関する情報はありません。
この問題を解決するには、 throwステートメント を使用して、ロールバックイベントの後に問題のあるエラーを再スローできます このフィドル(リンク)で表示 または省略されたサンプル未満:
BEGIN TRY
BEGIN TRANSACTION
--Your code goes here
COMMIT TRANSACTION
END TRY
BEGIN CATCH
--Some other error handling code here
ROLLBACK TRANSACTION;
THROW;
END CATCH
キーはCATCHブロックが何をしているのかを知ることです。TRYブロックでエラーが発生すると、ブロックが消費され(IEが呼び出し元に戻されない)、独自のコードでエラーを処理できるようになります。
あなたの場合、CATCHブロックは単にロールバックを実行するだけです。つまり、エラーが呼び出し元のプロシージャに戻されることはありません。THROWを追加すると、手動でエラーを呼び出し元に返すことによって解決されます(この場合は外部プロシージャ)。
スローを使用したくない場合は、 [〜#〜] raiserror [〜#〜] を使用して、発生するエラーをより詳細に制御することもできます。