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)
取得しているエラーは、開いているトランザクションを持たずにロールバックしているためです(already commitまたはrollback)。ストアドプロシージャの構造をクリーンアップし、ストアドプロシージャ全体を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
名前が付けられている場合は、ロールバックするトランザクション名を指定する必要があります。それから始めます。
その後、トランザクションが失敗していることを伝えることができます(トランザクションが以前にコミットされていないことを確認してください)。
BEGIN TRAN Tr1
-- your code
ROLLBACK TRAN Tr1
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
クイックルックから-トランザクションの開始時にトランザクションに名前を付けたため(Tr1)、エラーハンドラで名前を参照していない可能性がありますか?