【问题标题】:An error occured while executing query with nested transactions使用嵌套事务执行查询时发生错误
【发布时间】:2015-01-30 07:25:06
【问题描述】:

我在尝试执行以下查询时遇到错误。

if exists (select null from sys.sysobjects where type='P' and name = 'myProc')
    drop PROCEDURE myProc
go

create procedure myProc
as
begin
    set nocount on
    set xact_abort on

    begin try
        declare @trancount int = @@trancount

        if @trancount = 0
            begin tran
        else
            save tran MySave

        raiserror ('123213123',16,1)

        if @trancount = 0
            commit
    end try 
    begin catch
        if @trancount = 0
            rollback
        else
            if XACT_STATE() = 1
                rollback tran MySave
            else
                rollback    
    end catch
end
go

begin tran
    EXEC myProc

if @@TRANCOUNT >0
    rollback

错误是

EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 1,当前计数 = 0。

我已经阅读了许多关于类似问题的主题,但到目前为止还不清楚我的情况是什么原因。 谁能解释我为什么会得到它以及我应该怎么做才能避免它。 提前致谢

更新。我可以像这样简化 MyProc 的代码

create procedure myProc
as
begin
    set nocount on
    set xact_abort on

    begin try
        begin tran
           raiserror ('123213123',16,1)
        commit
    end try 
    begin catch
        rollback
    end catch
end
go

它不能解决我的问题。出现同样的错误

【问题讨论】:

    标签: sql-server nested-transactions


    【解决方案1】:

    试试这个:

    ALTER PROCEDURE myProc
    AS
        BEGIN
            SET NOCOUNT ON
            SET XACT_ABORT ON
    
            BEGIN TRY
                DECLARE @trancount INT = @@trancount
    
                IF @trancount = 0
                    BEGIN TRAN
                ELSE
                    SAVE TRAN MySave
    
                RAISERROR ('123213123',16,1)
    
                IF @trancount = 0
                    COMMIT
            END TRY 
            BEGIN CATCH
                IF XACT_STATE() <> 0
                    AND @trancount = 0
                    ROLLBACK TRANSACTION;
            END CATCH
        END
    GO
    
    BEGIN TRAN
    EXEC myProc
    
    
    IF @@TRANCOUNT > 0
        ROLLBACK
    

    【讨论】:

    • trancount 是 MyProc 处理之前的事务计数。如果 trancount 等于 0,我开始一个 trancaction(开始 tran),然后,如果发生错误,回滚它,如果 @trancount > 0 这意味着我已经在一个外部事务中。所以我做了一个保存点
    • @Giorgi Nakeuri,是的,它有效。但我觉得这不是我真正想要的,在我们继续之前,当我进入 XACT_STATE() = 1
    • @zagrr,注释行 --SET XACT_ABORT ON
    猜你喜欢
    • 2019-08-24
    • 2018-06-22
    • 2019-01-04
    • 2014-04-25
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 2019-04-12
    • 2017-12-17
    相关资源
    最近更新 更多