单次Transcation的多次回滚

时间:2016-03-09 10:21:07

标签: sql-server commit rollback sqltransaction

我必须更新表中的多个行数。 我的要求是,如果由于任何原因,更新结果返回0,那么应该回滚整个事务。 同时,如果发生任何异常,则必须回滚完整的事务。

简而言之,如果update语句返回0或者在更新表时发生了任何异常,我需要回滚整个更新事务。

这是我使用的代码。

CREATE TYPE [DBO].[EMPLOYEETYPETABLETYPE] AS TABLE
( EmployeeStatusKey INT, EmployeeStatusName VARCHAR(50) )

CREATE PROCEDURE [dbo].[usp_UpdateEmployeeStatusType]

@EmploymentStatusDetails [DBO].[EMPLOYEETYPETABLETYPE] READONLY 

AS
 BEGIN

SET NOCOUNT ON;

DECLARE @TransactionName varchar(20) = 'UpdateEmployeeStatus';

DECLARE @rowcount1 INT

    BEGIN

    BEGIN TRY
        BEGIN TRANSACTION @TransactionName

            UPDATE  ES1
            SET
                ES1.EmployeeStatusName=ES2.EmployeeStatusName

            FROM 
                 [dbo].[EmployeeStatusTypes] ES1
            INNER JOIN 
                @EmploymentStatusDetails ES2
            ON 
                ES1.EmployeeStatusKey= ES2.EmployeeStatusKey

            SET
                @ROWCOUNT1=@@ROWCOUNT

            IF @rowcount1 =0
                GOTO PROBLEM

        PROBLEM:
        ROLLBACK TRAN  @TransactionName
    COMMIT
END TRY
    BEGIN CATCH
        SET @ROWCOUNT1=0
        ROLLBACK TRAN @TransactionName
    END CATCH

    IF @rowcount1 =0
        SELECT  -178,@rowcount1;
    ELSE
        SELECT  178,@rowcount1;
    END 


 END

我将数据表从C#代码传递给存储过程。 当我执行Sp时,没有抛出错误但是当我从C#代码中调用它时,我得到了异常

  

异常:ROLLBACK TRANSACTION请求没有相应的BEGIN TRANSACTION。

请提前帮助并表示感谢....

2 个答案:

答案 0 :(得分:0)

删除那个糟糕的GOTO

TContext

并查看TRY-CATCH文档。您必须通过检查XACT_STATE()值来检查是否有任何要提交或回滚的事务。

答案 1 :(得分:0)

我用简化的脚本测试了你的脚本:

BEGIN TRY
    print 'A:' + cast(@@trancount as varchar)
    BEGIN TRANSACTION tranName

    print 'B:' + cast(@@trancount as varchar)
    GOTO PROBLEM -- you can comment this to simulate there is no error

    PROBLEM:
    begin
      ROLLBACK TRAN  tranName
      print 'there is a problem'
    end
    print 'C:' + cast(@@trancount as varchar)
    COMMIT
END TRY
BEGIN CATCH
    print 'D:' + cast(@@trancount as varchar)
    ROLLBACK TRAN tranName
END CATCH

出现问题时,输出就像

A:0
B:1
there is a problem
C:0
D:0
Msg 3903, Level 16, State 1, Line 18
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.

如果我评论GOTO PROBLEM所以没有问题,输出就像这样:

A:0
B:1
there is a problem
C:0
D:0
Msg 3903, Level 16, State 1, Line 18
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.

你看到GOTO下的部分仍然在执行。

最后,COMMIT仍然在没有可用事务的地方发生,因此COMMIT抛出错误。这意味着您的脚本会抛出异常。

如果你摆脱GOTO,你会很好。无论如何,使用GOTO是一种不好的做法。