我已尝试将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)
答案 0 :(得分:11)
您获得的错误是因为您在没有打开事务的情况下回滚(您已经已经提交或回滚)。考虑清理存储过程的结构,尝试将整个存储过程作为一个事务执行,然后在发生错误时回滚。您还可以通过检查事务是否已打开来测试是否需要回滚:
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
答案 1 :(得分:1)
如果已命名,则需要指定要回滚的事务名称。 从那开始。
之后你可以告诉我们交易失败了(确保以前没有提交交易)。
BEGIN TRAN Tr1
-- your code
ROLLBACK TRAN Tr1
答案 2 :(得分:0)
快速查看 - 可能是因为您在启动它时命名了您的事务(Tr1),但没有在错误处理程序中引用该名称?
答案 3 :(得分:0)
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