SQL Server错误 - EXECUTE之后的事务计数表示BEGIN和COMMIT语句的数量不匹配

时间:2017-02-20 14:35:41

标签: sql sql-server tsql transactions

我写了这个存储过程

ALTER PROCEDURE [dbo].[CERRARVIAJE] 
(   @ViajeID INT, 
    @Reloj MONEY, 
    @Peaje MONEY, 
    @Equipaje MONEY, 
    @Adicional MONEY, 
    @Plus MONEY, 
    @MontoAutorizado MONEY, 
    @CerrarEnBase BIT, 
    @UsuarioCierra INT, 
    @Motivo Varchar(100), 
    @Fecha DATETIME
)
AS
BEGIN 
    SET NOCOUNT ON;
    SET XACT_ABORT ON

    DECLARE @NuevoEstado INT
    DECLARE @DireccionDestino VARCHAR(200)
    DECLARE @Punto Geography
    DECLARE @movil INT
    DECLARE @chofer INT
    DECLARE @Cierre VARCHAR(10)
    DECLARE @VisualId VARCHAR(10)

    IF @Fecha IS NULL
    BEGIN
        SET @Fecha = GETDATE()
    END

    IF @ViajeID IS NOT NULL
    BEGIN
        SELECT  @movil = C.MovilID, 
                @chofer = V.ChoferID , 
                @VisualId = V.VisualID, 
                @DireccionDestino = DireccionDestino, 
                @Punto = Destino 
        FROM CHOFERES C (NOLOCK)
        INNER JOIN VIAJES V (NOLOCK)
            ON C.Id = V.ChoferId  
        WHERE V.ID = @ViajeID

        --Si el usuario que cierra es el chofer, se obtiene su id de usuario
        IF @UsuarioCierra = -1
        BEGIN
            SELECT @UsuarioCierra = Ch.UsuarioID From Viajes V (NOLOCK), Choferes Ch (NOLOCK) Where V.ID = @ViajeID AND Ch.ID = V.ChoferID
        END

        --Se establece el nuevo estado que tendrá el viaje
        IF @CerrarEnBase = 0 
        BEGIN
            SET @NuevoEstado  = 13 --Completado
        END
        ELSE
        BEGIN
            SET @NuevoEstado  = 18 --Cierra Base
        END

        --El motivo sólo es necesario si el viaje lo cerró la base
        IF @CerrarEnBase = 0
        BEGIN
            SET @Motivo = ''
        END

        --Si el operador no puso dirección de destino al crear el viaje se busca mediante la tabla Recorridos
        IF @DireccionDestino IS NULL
        BEGIN
            SELECT  @DireccionDestino = Direccion, 
                    @Punto = Punto 
            FROM Recorridos (NOLOCK) 
            WHERE   ViajeID = @ViajeID 
                    AND ID IN   (SELECT MAX(ID) MID 
                                FROM Recorridos (NOLOCK) 
                                WHERE ViajeID = @ViajeID)
        END

        DECLARE @Success    BIT
        SELECT @Success = 0
        WHILE @Success = 0

        BEGIN TRY
            IF @@TRANCOUNT > 0
            BEGIN
                SAVE TRANSACTION CERRARVIAJE
            END
            ELSE
            BEGIN
                BEGIN TRANSACTION
            END

            --se actualizan los datos del viaje que se va a cerrar       
            UPDATE  Viajes 
            SET     EstadoID = @NuevoEstado, 
                    FechaCompletado = @Fecha, 
                    CerroUsuarioID = @UsuarioCierra, 
                    MotivoCerrarBase = @Motivo, 
                    Destino = @Punto, 
                    DireccionDestino = @DireccionDestino
            WHERE ID = @ViajeID

            --se cambia el estado del móvil en calle
            UPDATE MOVILESENCALLE SET ESTADO = 1 WHERE ID = @movil

            --se guarda el registro en ViajesLog
            INSERT INTO [dbo].[ViajesLog]
                        ([Id],[TipoViajeId],[EstadoId],[UsuarioId],[ChoferId],[SubEmpresaId],[PINPasajero],[FechaSolicitado],[FechaUltimoEstado],[FechaAceptado],[FechaPasajeroABordo],[FechaCompletado]
                        ,[FechaCancelado],[FechaCanceladoPasajero],[Origen],[DireccionOrigen],[Destino],[DireccionDestino],[UbicacionActual],[DireccionUbicacionActual],[FlotaIDOriginal],[FechaUniverso]
                        ,[VISUALID],[FechaCreacion],[Observaciones],[Observaciones2],[NoFumador],[AnimalDom],[ServicioVan],[Ticketera],[BaulVacio],[AireAcondicionado],[MotivoCancelacionPasajero],[NumeroViajeCliente]
                        ,[NumeroSiniestro],[TipoMovilId],[CerroUsuarioId],[TienePremio],[Premio],[RequiereVoucher],[MotivoCerrarBase],[EsMensajeria],[FechaObjetivo],[Autorizacion]
                        ,[NombreApellidoPasajero],[CelularPasajero],[ZonaID],[OperadorID],[AutorizacionUsuarioId],[Condicional], [MovilId])
            SELECT V.[Id],[TipoViajeId],[EstadoId],V.[UsuarioId],[ChoferId],[SubEmpresaId],[PINPasajero],[FechaSolicitado],[FechaUltimoEstado],[FechaAceptado],[FechaPasajeroABordo],[FechaCompletado]
                    ,[FechaCancelado],[FechaCanceladoPasajero],[Origen],[DireccionOrigen],[Destino],[DireccionDestino],[UbicacionActual],[DireccionUbicacionActual],[FlotaIDOriginal],[FechaUniverso]
                    ,[VISUALID],[FechaCreacion],V.[Observaciones],[Observaciones2],[NoFumador],[AnimalDom],[ServicioVan],[Ticketera],[BaulVacio],[AireAcondicionado],[MotivoCancelacionPasajero],[NumeroViajeCliente]
                    ,[NumeroSiniestro],[TipoMovilId],[CerroUsuarioId],[TienePremio],[Premio],[RequiereVoucher],[MotivoCerrarBase],[EsMensajeria],[FechaObjetivo],[Autorizacion]
                    ,[NombreApellidoPasajero],[CelularPasajero],[ZonaID],[OperadorID],[AutorizacionUsuarioId],[Condicional], C.MovilId
            FROM [dbo].[Viajes] V (NOLOCK) 
            LEFT JOIN Choferes C (NOLOCK)
                ON V.ChoferId = C.Id
            WHERE V.ID = @ViajeID 

            --se elimina el registro de la tabla Viajes
            DELETE FROM Viajes 
            WHERE ID = @ViajeID

            --se elimina el registro de la tabla MontosViajes
            DELETE FROM [dbo].[MontosViajes] WHERE 
            ViajeID = @ViajeID

            --se crea el nuevo registro en la tabla MontosViajes
            INSERT INTO [dbo].[MontosViajes] ([ViajeId],[Reloj],[Peaje],[Equipaje],[Adicional],[Plus],[MontoTotal],
                    [MontoNetoChofer],[MontoTaxiCorp],[MontoFlotaRecibioViaje],[MontoFlotaRealizoViaje],
                    [FlotaRecibioViajeID],[FlotaRealizoViajeID],[SubEmpresaID])
            SELECT TOP 1    @ViajeID, 
                            @Reloj, 
                            @Peaje, 
                            @Equipaje, 
                            @Adicional, 
                            @Plus, 
                            @MontoAutorizado,
                            @MontoAutorizado * (1 - F.DescuentoPorcentaje / 100.0) - F.DescuentoFijoTotal,  
                            0, 
                            CASE WHEN V.FlotaIdOriginal = SF.FlotaID THEN F.DescuentoFijoTotal 
                                ELSE F.DescuentoFijoPropio 
                            END + @MontoAutorizado * (F.DescuentoPorcentaje / 100.0),
                            CASE WHEN V.FlotaIdOriginal = SF.FlotaID THEN 0 
                                ELSE F.DescuentoFijoOtraFlota 
                            END,
                            V.FlotaIdOriginal, 
                            SF.FlotaID, 
                            V.SubEmpresaID
            FROM    ViajesFull V (NOLOCK) 
            INNER JOIN Choferes C (NOLOCK)
                ON V.ChoferId = C.Id
            INNER JOIN Moviles M (NOLOCK)
                ON C.MovilId = M.Id  
            INNER JOIN SubFlotas SF (NOLOCK)
                ON M.SubFlotaID = SF.ID
            INNER JOIN FLotas F (NOLOCK)
                ON V.FlotaIdOriginal = F.ID
            WHERE V.ID = @ViajeID 

            --se establece texto para guardar en el log
            IF @CerrarEnBase = 0
            BEGIN
                SET @Cierre = 'FINAL '
            END     
            ELSE
            BEGIN
                SET @Cierre = 'A BASE '
            END

            --se guarda registro en el log de acciones
            INSERT INTO AccionesLog (ChoferID, MovilID, ViajeID, UsuarioID, Accion, Stamp)
            VALUES (@chofer, @movil, @ViajeID, @UsuarioCierra, 'CERRO VIAJE ' + @Cierre + @VisualId + ' POR ' + CONVERT(VARCHAR, @MontoAutorizado), GETDATE())
        lbexit:
                IF @@TRANCOUNT = 0
                    COMMIT TRAN;

                SET @Success = 1 -- To exit the loop
            END TRY                     

            BEGIN CATCH

                DECLARE @ERROR INT, @MESSAGE VARCHAR(4000), @XSTATE INT;
                SELECT @ERROR = ERROR_NUMBER(), @MESSAGE = ERROR_MESSAGE(), @XSTATE = XACT_STATE();

                --IF @XSTATE = -1
                --  ROLLBACK;
                IF --@XSTATE = 1 AND 
                @@TRANCOUNT = 0
                    ROLLBACK;
                IF --@XSTATE = 1 AND 
                @@TRANCOUNT > 0
                    ROLLBACK TRANSACTION CERRARVIAJE;


                IF @ERROR IN (1204, -- SqlOutOfLocks
                                1205, -- SqlDeadlockVictim
                                1222 -- SqlLockRequestTimeout
                                )
                    BEGIN
                        -- This delay is to give the blocking 
                        -- transaction time to finish.
                        -- So you need to tune according to your 
                        -- environment
                        WAITFOR DELAY '00:00:02'  
                    END 
                ELSE    
                    -- If we don't have a handler for current error
                    -- then we throw an exception and abort the loop
                    THROW;
            END CATCH
    END
END

我遇到了这个错误:

  

EXECUTE之后的事务计数表示BEGIN和COMMIT语句的数量不匹配。先前的计数= 0,当前计数= 1。

0 个答案:

没有答案