消息3902,级别16,状态1. COMMIT TRANSACTION请求没有相应的BEGIN TRANSACTION

时间:2011-10-22 13:52:07

标签: sql sql-server sql-server-2005 sql-server-2008

DECLARE @cnt_inv int,
        @cnt_jrn int, 
        @pl_per varchar(2), 
        @pl_yr  varchar(4), 
        @pl_jrn varchar (6), 
        @pl_inv varchar (6)

IF @@ERROR <> 0
BEGIN
BEGIN TRANSACTION JD_Imp


            IF @cnt_inv > 0 
            BEGIN
            BEGIN TRANSACTION JD_Inv



        COMMIT TRANSACTION JD_Inv; 
                    PRINT N'The Invoice Commits DONE.';
        END

            IF @cnt_jrn > 0 
            BEGIN
            BEGIN TRANSACTION JD_Jrn


        COMMIT TRANSACTION JD_Jrn;  
                    PRINT N'The Journals Commits DONE.';
        END
COMMIT TRANSACTION JD_Imp;
END

2 个答案:

答案 0 :(得分:2)

您问题的核心是:

IF @cnt_jrn > 0 
        BEGIN TRANSACTION JD_Jrn

所有这一切只会在@cnt_jrn > 0开始新的交易。无论条件如何,它仍然会执行下面的所有代码。因此,如果@cnt_jrn <= 0,它将在没有启动它的情况下调用commit transaction JD_Jrn

您需要将任意多语句if正文的正文与beginend括起来。例如:

IF @cnt_jrn > 0 
BEGIN
        BEGIN TRANSACTION JD_Jrn

        ... code ...
END

但是您在事务中附上单个insertupdate语句,这是不必要的。 SQL操作保证是原子操作,因此如果您跨越多个操作,则只需要一个事务。

答案 1 :(得分:0)

问题解决了.....

(a)使用Begin ... END Blocks确实解决了错误消息Msg 3902 ..我注意到没有BEGIN..END块,以前的程序运行仍然会挂起未提交

(b)IF @@ ERROR&lt;&gt; 0 BEGIN将永远为真,所以难怪内部的脚本块没有被执行。

(c)由于(b),调试器没有移过IF语句。

非常感谢亚当。