1. ホーム
  2. sql

[解決済み] EXECUTE後のトランザクションカウントは、BEGIN文とCOMMIT文の数が不一致であることを示しています。以前のカウント = 1、現在のカウント = 0

2022-02-12 10:40:38

質問

を持っています。 Insert にデータを供給するストアドプロシージャです。 Table1 を取得し Column1 から値を取得します。 Table1 で、2番目のストアドプロシージャを呼び出して、Table2 にデータを供給します。

しかし、2つ目のストアドプロシージャを次のように呼び出すと

Exec USPStoredProcName

以下のようなエラーが発生します。

EXECUTE の後のトランザクション・カウントは、BEGIN 文と COMMIT 文の数が不一致であることを示しています。以前のカウント = 1、現在のカウント = 0。

他の質問での回答も読みましたが、具体的にどこでコミットカウントが狂っているのかがわかりません。

どうすればいいですか?

TRY/CATCHブロックがある場合、トランザクション中止例外をキャッチして続行していることが原因である可能性があります。CATCHブロックでは、常に XACT_STATE() で、中断されたトランザクションやコミット不能な(運命的な)トランザクションを適切に処理します。呼び出し側がトランザクションを開始し、呼び出し側が例えばデッドロック(トランザクションを中断した)に当たった場合、呼び出し側はどのようにしてトランザクションが中断され、「通常通りのビジネス」を継続すべきではないことを呼び出し側に伝えるつもりでしょうか?唯一可能な方法は、例外を再発生させ、呼び出し側にその状況を処理させることである。もしあなたが中断されたトランザクションを黙って飲み込み、呼び出し側がまだ元のトランザクションにいると仮定して続けるなら、騒乱だけが保証されます(そしてあなたが得るエラーは、エンジンがそれ自身を保護しようとする方法です)。

をご覧になることをお勧めします。 例外処理とネストされたトランザクション には、ネストされたトランザクションと例外で使用できるパターンが示されています。

create procedure [usp_my_procedure_name]
as
begin
    set nocount on;
    declare @trancount int;
    set @trancount = @@trancount;
    begin try
        if @trancount = 0
            begin transaction
        else
            save transaction usp_my_procedure_name;

        -- Do the actual work here

lbexit:
        if @trancount = 0
            commit;
    end try
    begin catch
        declare @error int, @message varchar(4000), @xstate int;
        select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
        if @xstate = -1
            rollback;
        if @xstate = 1 and @trancount = 0
            rollback
        if @xstate = 1 and @trancount > 0
            rollback transaction usp_my_procedure_name;

        raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
    end catch
end
go