Home > front end >  Stored Procedure Error on Commit and Begin Statements
Stored Procedure Error on Commit and Begin Statements

Time:09-21

ERROR

Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.

I get this error in my Stored Procedure that I cannot see where.

ALTER PROCEDURE [dbo].[UpsertServiceTicket]
    @TransactionType INT,
    @Id INT = NULL,
    @CreationDateTime DATETIME = GETDATE,
    @Issue VARCHAR(MAX),
    @ReportedDateTime DATETIME = NULL,
    @ResolutinoDateTime DATETIME = NULL,
    @CreatedBy INT = NULL,
    @ServiceRequestNumber NVARCHAR(MAX),
    @Status VARCHAR(MAX) = NULL,
    @IsDeleted BIT = 0,
    @LocationId INT,
    @SubLocationId INT,
    @RequestorId INT,
    @ConfirmedBy INT = NULL,
    @DepartmentId INT,
    @ErrorMessage NVARCHAR(1000) OUTPUT,
    @ErrorCode SMALLINT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        BEGIN TRANSACTION

            IF (@TransactionType = 0)
                INSERT INTO ServiceTickets (
                    CreationDateTime
                    , Issue 
                    , ReportedDateTime
                    , ResolutionDateTime
                    , CreatedBy
                    , ServiceRequestNumber
                    , [Status]
                    , IsDeleted
                    , LocationId
                    , SubLocationId
                    , RequestorId
                    , ConfirmerId
                    , DepartmentId
                    )
                VALUES (
                    @CreationDateTime
                    , @Issue
                    , @ReportedDateTime
                    , @ResolutinoDateTime
                    , @CreatedBy
                    , @ServiceRequestNumber
                    , @Status
                    , @IsDeleted
                    , @LocationId
                    , @SubLocationId
                    , @RequestorId
                    , @ConfirmedBy
                    , @DepartmentId
                )
        -- updating the service ticket table
            ELSE
                UPDATE      ServiceTickets
                SET         CreationDateTime        = @CreationDateTime
                            , Issue                 = @Issue
                            , ReportedDateTime      = @ReportedDateTime
                            , ResolutionDateTime    = @ResolutinoDateTime
                            , CreatedBy             = @CreatedBy
                            , ServiceRequestNumber  = @ServiceRequestNumber
                            , [Status]              = @Status
                            , IsDeleted             = @IsDeleted
                            , LocationId            = @LocationId
                            , SubLocationId         = @SubLocationId
                            , RequestorId           = @RequestorId
                            , ConfirmerId           = ConfirmerId
                            , DepartmentId          = DepartmentId
                WHERE Id = @Id
 
            SET @ErrorMessage = ERROR_MESSAGE()
            SET @ErrorCode = @@ERROR
            IF (@ErrorCode = 0)
                COMMIT TRANSACTION
        END TRY
    BEGIN CATCH
        SET @ErrorMessage = ERROR_MESSAGE()
        SET @ErrorCode = @@ERROR;
  
        IF @ErrorCode > 0
          ROLLBACK TRANSACTION
    END CATCH
END

CodePudding user response:

Your error handling code is incorrect, as it does not rollback or commit the transaction in certain cases

It also swallows exceptions and instead returns an error code. You are far better off just letting the error bubble up back to the client. You should use SET XACT_ABORT ON to ensure a rollback.

Given that you are only ever executing one statement, you don't even need a transaction anyway

ALTER PROCEDURE [dbo].[UpsertServiceTicket]
    @TransactionType INT,
    @Id INT = NULL,
    @CreationDateTime DATETIME = NULL,
    @Issue VARCHAR(MAX),
    @ReportedDateTime DATETIME = NULL,
    @ResolutinoDateTime DATETIME = NULL,
    @CreatedBy INT = NULL,
    @ServiceRequestNumber NVARCHAR(MAX),
    @Status VARCHAR(MAX) = NULL,
    @IsDeleted BIT = 0,
    @LocationId INT,
    @SubLocationId INT,
    @RequestorId INT,
    @ConfirmedBy INT = NULL,
    @DepartmentId INT
AS

    SET NOCOUNT, XACT_ABORT ON;

    SET @CreationDateTime = ISNULL(@CreationDateTime, GETDATE());

    IF (@TransactionType = 0)
        INSERT INTO ServiceTickets (
                    CreationDateTime
                    , Issue 
                    , ReportedDateTime
                    , ResolutionDateTime
                    , CreatedBy
                    , ServiceRequestNumber
                    , [Status]
                    , IsDeleted
                    , LocationId
                    , SubLocationId
                    , RequestorId
                    , ConfirmerId
                    , DepartmentId
                    )
                VALUES (
                    @CreationDateTime
                    , @Issue
                    , @ReportedDateTime
                    , @ResolutinoDateTime
                    , @CreatedBy
                    , @ServiceRequestNumber
                    , @Status
                    , @IsDeleted
                    , @LocationId
                    , @SubLocationId
                    , @RequestorId
                    , @ConfirmedBy
                    , @DepartmentId
                );
        -- updating the service ticket table
        ELSE
            UPDATE      ServiceTickets
                SET         CreationDateTime        = @CreationDateTime
                            , Issue                 = @Issue
                            , ReportedDateTime      = @ReportedDateTime
                            , ResolutionDateTime    = @ResolutinoDateTime
                            , CreatedBy             = @CreatedBy
                            , ServiceRequestNumber  = @ServiceRequestNumber
                            , [Status]              = @Status
                            , IsDeleted             = @IsDeleted
                            , LocationId            = @LocationId
                            , SubLocationId         = @SubLocationId
                            , RequestorId           = @RequestorId
                            , ConfirmerId           = ConfirmerId
                            , DepartmentId          = DepartmentId
                WHERE Id = @Id;

If you do need a transaction to do a proper Upsert, use this template, with HOLDLOCK, UPDLOCK hints. You do not need a BEGIN CATCH as XACT_ABORT ON will handle the rollback

CodePudding user response:

Use this pattern:

Begin Tran <TransactionName>

BEGIN TRY
   --Some Statements
   Commit Tran <TransactionName>
END TRY
BEGIN CATCH
    DECLARE @Error NVARCHAR(4000)
    SET @Error = ERROR_MESSAGE()
    ROLLBACK TRAN <TransactionName>
    RAISERROR (@Error, 16, 1)
END CATCH
  • Related