【问题标题】:ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTIONROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION
【发布时间】:2014-04-25 14:32:44
【问题描述】:

我尝试将 COMMIT TRAN 置于 if else 循环中,但仍然出现此错误。

我必须为一个学生注册一个班级。如果报名后座位数为负数,我只好反转并打印一条消息说不能报名。我放了其他错误消息只是为了看看事务是如何工作的。

CREATE PROCEDURE dbo.EnrollStudent ( @CourseID  AS INTEGER,
                                     @StudentID AS VARCHAR(20) ) AS
BEGIN
   DECLARE @StatusID INTEGER
   DECLARE @Status VARCHAR(50)
   DECLARE @CurrentSeats INTEGER
   DECLARE @ErrorCode INTEGER
   SET @StatusID=0



      IF EXISTS (SELECT 1 
                    FROM dbo.CourseEnrollment 
                    WHERE dbo.CourseEnrollment.CourseId=@CourseID AND dbo.CourseEnrollment.StudentId=@StudentID )
        BEGIN

         BEGIN TRAN Tr1
         SET @StatusID = 1
         SELECT @ErrorCode=@@ERROR
         IF (@ErrorCode<>0) GOTO OTHERPROBLEM
         ELSE 
         COMMIT TRAN Tr1

        END


     IF EXISTS ( SELECT 1
                    FROM dbo.CourseEnrollment
                    FULL OUTER JOIN dbo.Courses
                    ON dbo.Courses.CourseId=@CourseID     
                    WHERE dbo.CourseEnrollment.StudentId<>@StudentID  AND dbo.Courses.Faculty IS NULL ) 
            BEGIN
            BEGIN TRAN Tr2
                SET @StatusID=2
                SELECT @ErrorCode=@@ERROR
                 IF (@ErrorCode<>0) GOTO OTHERPROBLEM2
                 ELSE
                 COMMIT TRAN Tr2

                 END



    IF @StatusID=0
    BEGIN
        IF EXISTS ( SELECT 1
                    FROM dbo.Courses    
                    WHERE dbo.Courses.CourseId=@CourseID AND dbo.Courses.Faculty IS NOT NULL )

                BEGIN


                BEGIN TRAN Tr3

                SET @StatusID=3


                BEGIN TRAN InsertingValues
                INSERT INTO dbo.CourseEnrollment (dbo.CourseEnrollment.StudentId,dbo.CourseEnrollment.CourseId)
                                                VALUES          (@StudentID,@CourseID);

                SELECT @ErrorCode=@@ERROR
                 IF (@ErrorCode<>0) GOTO InsertProblem
                 ELSE
                 COMMIT TRAN InsertingValues




                BEGIN TRAN UpdateCourses
                UPDATE dbo.Courses  
                    SET OpenSeats = OpenSeats-1 
                       WHERE dbo.Courses.CourseId = @CourseID

                SELECT @ErrorCode=@@ERROR
                 IF (@ErrorCode<>0) GOTO UpdateProblem
                 ELSE
                 COMMIT TRAN UpdateCourses




                SELECT @CurrentSeats=OpenSeats  
                    FROM dbo.Courses
                        WHERE dbo.Courses.CourseId = @CourseID

                        IF (@CurrentSeats<0) GOTO PROBLEM
                        ELSE
                        COMMIT TRAN Tr3


                END

    END



    OTHERPROBLEM:
         BEGIN
            PRINT 'Unable to set status'
            ROLLBACK TRAN
         END


    OTHERPROBLEM2:
                 BEGIN
                     PRINT 'Unable to set status'
                     ROLLBACK TRAN
                 END


     UpdateProblem:
                 BEGIN
                     PRINT 'Not able to update values'
                     ROLLBACK TRAN InsertingValues
                 END



    InsertProblem:
                 BEGIN
                     PRINT 'Not able to insert'
                     ROLLBACK TRAN InsertingValues
                 END



    PROBLEM:
                BEGIN
                    PRINT 'Seats Full!'
                    ROLLBACK TRAN
                END




     IF @StatusID = 1
        BEGIN  
         SET @Status = 'The Student is already enrolled'
        END;

     ELSE IF @StatusID = 2
         BEGIN 
            SET @Status = 'Cannot enroll until faculty is selected' 
         END

     ELSE IF @StatusID = 3
         BEGIN 
            SET @Status = 'Student Enrolled' 
        END

   SELECT @Status

END;

这正确更新了表格,但出现以下错误:

(1 row(s) affected)

(1 row(s) affected)
Unable to set status
Msg 3903, Level 16, State 1, Procedure EnrollStudent, Line 101
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
Unable to set status
Msg 3903, Level 16, State 1, Procedure EnrollStudent, Line 108
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
Not able to update values
Msg 3903, Level 16, State 1, Procedure EnrollStudent, Line 115
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
Not able to insert
Msg 3903, Level 16, State 1, Procedure EnrollStudent, Line 123
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
Seats Full!
Msg 3903, Level 16, State 1, Procedure EnrollStudent, Line 131
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.

(1 row(s) affected)

【问题讨论】:

  • 我很确定您的第二个查询(带有FULL OUTER JOIN 的查询)没有告诉您有用的信息。我至少无法理解您期望它会告诉您什么,或者为什么这会相关。此外,除非您将 整个 事物包装在单个序列化事务中,否则您不能相信您的结果;可能会添加太多学生,获得否定席位,根本不报告(未来)否定席位......这对于并发系统实际上并不安全。就我个人而言,我可能会先 INSERTing 进入一个具有高分辨率时间戳且没有事务的表。

标签: sql sql-server-2008 transactions


【解决方案1】:

您遇到的错误是因为您在没有打开事务的情况下回滚(您已经提交或回滚)。考虑清理存储过程的结构,尝试将整个存储过程作为一个事务执行,然后在发生错误时回滚。您还可以通过检查事务是否打开来测试是否需要回滚:

BEGIN TRANSACTION;
BEGIN TRY

   --execute all your stored proc code here and then commit
   COMMIT;

END TRY
BEGIN CATCH

   --if an exception occurs execute your rollback, also test that you have had some successful transactions
   IF @@TRANCOUNT > 0 ROLLBACK;  

END CATCH

【讨论】:

    【解决方案2】:

    如果被命名,则需要指定要回滚的事务名称。 从那开始。

    之后您可以告诉我们哪个事务失败了(确保之前没有提交过该事务)。

    BEGIN TRAN Tr1
    
    -- your code 
    
    ROLLBACK TRAN Tr1
    

    【讨论】:

    • 由于某种原因,命名事务仍然会出现这种情况,并且TRANSACTION这个词只出现了两次。一次开始,一次回滚。
    【解决方案3】:

    快速浏览一下 - 可能是因为您在启动事务时已命名事务 (Tr1),但未在错误处理程序中引用该名称?

    【讨论】:

    • 也许尝试给 try catch 一个机会,而不是 @@Error
    • 没有人可以帮忙吗? :O
    【解决方案4】:
    DECLARE @Error varchar(max)        
    SET @Error = ''        
    
    BEGIN TRY        
    
     INSERT INTO OPERACION(CONTRATOID,FLUJO,MONTO,ID_ORIGINAL,ID_TRX,ESTADO,TIPO,REFERENCIA,        
     US_CREA,US_ACT,FEC_CRE,REQUEST,RESPONSE)        
     VALUES(@P_CONTRATOID,@P_FLUJO,@P_MONTO,@P_ID_ORIGINAL,@P_ID_TRX,@P_ESTADO,        
     @P_TIPO,@P_REFERENCIA,@P_US_CREA,@P_US_ACT,getdate(),@P_REQUEST,@P_RESPONSE)        
    
    END TRY        
    BEGIN CATCH        
     SELECT @Error = 'err: '+ ERROR_MESSAGE()      
    
     ROLLBACK ;  
    END CATCH        
    
    SELECT @Error 
    

    【讨论】:

    • 感谢您的回答;你能在你的代码中添加一些描述来突出原始帖子的错误吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多