SQL - StoredProcedure con transacciones anidadas a veces se ejecute correctamente y a veces no

 
Vista:
sin imagen de perfil
Val: 6
Ha aumentado 1 puesto en SQL (en relación al último mes)
Gráfica de SQL

StoredProcedure con transacciones anidadas a veces se ejecute correctamente y a veces no

Publicado por Manuel Alejandro (4 intervenciones) el 27/03/2020 16:50:36
¡Hola!

Me encuentro realizando un procedure para registrar ventas. Se pueden realizar ventas por productos que se encuentran en inventario o por productos que se producen al momento de realizar la venta. Me encuentro realizando pruebas con productos que requieren registrar una producción (Entra al procedure Registrar_Produccion) y posteriormente al procedure Registrar_Detalle_Venta.

El problema es que al ejecutarlo devuelve este error "Registrar_Produccion Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0." Se que va relacionado con la cantidad COMMITS y ROLLBACK dentro del procedure ya que antes me había sucedido algo similar y era porque me faltaba agregar ROLLBACK pero esta vez no puedo detectar que es lo que lo ocasiona.

Vuelvo a recalcarlo, este error lo devuelve el procedure Registrar_Venta, el cual ejecuta los procedures Registrar_Produccion y Registrar_Detalle_Venta.

P.D. Estoy probando este procedure en una base de datos alojada en el mismo ordenador en donde realizo las pruebas. Cuando recién enciendo la computadora el procedure se ejecuta correctamente. Pero quiero intentar ejecutarlo nuevamente es que sucede este error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
CREATE PROCEDURE Registrar_Venta
@IdCliente int,
@MetodoPago varchar (18),
@IdSucursal tinyint,
@IdPersonal int,
@DetalleVentaType DetalleVentaType READONLY,
@TablaDetalleProduccion DetalleProduccionType READONLY,
@Tiro varchar(10) = null,
@Obra varchar(100)
AS
BEGIN
    BEGIN TRY
        BEGIN TRAN
            DECLARE @NumeroRemision int
            SET @NumeroRemision = (Select ISNULL(MAX(NumeroRemision),0)+1 from Venta)
 
            DECLARE @Error varchar(200)
            SET @Error = null
 
            Insert into Venta (NumeroRemision,IdCliente, FechaVenta, MetodoPago, IdSucursal, IdPersonal, Cancelada)
            values (@NumeroRemision, @IdCliente, GETDATE(), @MetodoPago, @IdSucursal, @IdPersonal, 0)
 
            -------------------------Se registra la produccion si es que hay----------------------------
            IF (Select COUNT(IdProducto) from @TablaDetalleProduccion) > 0 BEGIN
                DECLARE @IdUsuario int
                SET @IdUsuario = (Select TOP 1 IdUsuario from Usuario WHERE IdPersonal = @IdPersonal)
 
                DECLARE @CantidadProducida decimal(16,2)
                SET @CantidadProducida = (Select Cantidad from @DetalleVentaType)
                EXEC Registrar_Produccion
                @TablaDetalleProduccion = @TablaDetalleProduccion,
                @CantidadProducida = @CantidadProducida,
                @IdCliente = @IdCliente,
                @IdSucursal = @IdSucursal,
                @Tiro = @Tiro,
                @Obra = @Obra,
                @IdUsuario = @IdUsuario,
                @SelectFinal = 0,
                @Error = @Error OUT
 
                IF @Error IS NOT NULL BEGIN
                    IF @@TRANCOUNT > 0
                        ROLLBACK TRAN
 
                    Select @Error Error
                    RETURN
                END
            END
            ------------------------------------------------------------------------------
 
            --------------------------Se registra el detalle de la venta-----------------------------------------
            DECLARE @IdProducto int
            DECLARE @Cantidad decimal(16,2)
            DECLARE @Descuento decimal(5,2)
            DECLARE @Importe decimal(16,2)
            DECLARE @MetodoEntrega varchar(60)
            DECLARE CursorDetalleVenta CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
            FOR SELECT * from @DetalleVentaType
 
            OPEN CursorDetalleVenta
            FETCH NEXT FROM CursorDetalleVenta INTO @IdProducto, @Cantidad, @Descuento, @Importe, @MetodoEntrega
            WHILE @@FETCH_STATUS = 0 BEGIN
 
                EXEC Registrar_Detalle_Venta
                @NumeroRemision = @NumeroRemision,
                @IdProducto = @IdProducto,
                @Cantidad = @Cantidad,
                @Descuento = @Descuento,
                @Importe = @Importe,
                @MetodoEntrega = @MetodoEntrega,
                @SelectFinal = 0,
                @Error = @Error OUT
 
                IF @Error IS NOT NULL BEGIN
                    IF @@TRANCOUNT > 0
                        ROLLBACK TRAN
 
                    SELECT @Error Error
                    RETURN
                END
 
                FETCH NEXT FROM CursorDetalleVenta INTO @IdProducto, @Cantidad, @Descuento, @Importe, @MetodoEntrega
            END
            ----------------------------------------------------------------------------------------------------------
 
        COMMIT TRAN
        SELECT ERROR_PROCEDURE() + ' ' + ERROR_MESSAGE() Error, @NumeroRemision NumeroRemision
 
    END TRY
 
    BEGIN CATCH
 
        IF @@TRANCOUNT > 0
            ROLLBACK TRAN
 
        SELECT ERROR_PROCEDURE() + ' ' + ERROR_MESSAGE() Error
    END CATCH
END

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
CREATE PROCEDURE Registrar_Produccion
@TablaDetalleProduccion DetalleProduccionType READONLY,
@CantidadProducida decimal(16,2),
@IdCliente int,
@IdSucursal tinyint,
@Tiro varchar(10),
@Obra varchar(100),
@IdUsuario int,
@SelectFinal bit = null,
@Error varchar(200) OUT
AS
BEGIN
    BEGIN TRY
        BEGIN TRAN
            IF(Select COUNT(*) from @TablaDetalleProduccion) = 0 BEGIN
                SET @Error = 'No se ingresó la materia prima utilizada para la producción'
 
                IF @SelectFinal = 1 OR @SelectFinal IS NULL
                    SELECT @Error Error
 
                IF @@TRANCOUNT > 0
                        ROLLBACK TRAN
                RETURN
            END
 
            DECLARE @IdProductoAProducir int
            SET @IdProductoAProducir = (Select TOP 1 IdProducto from @TablaDetalleProduccion)
 
            IF (Select COUNT(IdMateriaPrima) from Producto_MateriaPrima WHERE IdProducto = @IdProductoAProducir  AND Requerido = 1)
                <> (Select COUNT(IdMateriaPrima) from @TablaDetalleProduccion
                    WHERE IdMateriaPrima IN
                        (Select IdMateriaPrima from Producto_MateriaPrima WHERE IdProducto = @IdProductoAProducir AND Requerido = 1)
                    ) BEGIN
 
                    SET @Error = 'No se ingresaron todos los productos que son requeridos para este producto.'
 
                    IF @SelectFinal = 1 OR @SelectFinal IS NULL
                        SELECT @Error Error
 
                    IF @@TRANCOUNT > 0
                        ROLLBACK TRAN
                    RETURN
            END
 
            DECLARE @IdProduccion int
            SET @IdProduccion = (Select ISNULL(MAX(IdProduccion),0)+1 from Produccion)
 
            INSERT INTO Produccion (IdProduccion, CantidadProducida, IdCliente, Fecha, IdSucursal, Tiro, Obra)
                values (@IdProduccion, @CantidadProducida, @IdCliente, GETDATE(), @IdSucursal, @Tiro, @Obra)
 
            DECLARE @IdProducto int
            DECLARE @IdMateriaPrima int
            DECLARE @CantidadMPUsada decimal(16,2)
 
            DECLARE CursorDetalleProduccion CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
            FOR SELECT * from @TablaDetalleProduccion
 
 
            OPEN CursorDetalleProduccion
            FETCH NEXT FROM CursorDetalleProduccion INTO @IdProducto, @IdMateriaPrima, @CantidadMPUsada
            WHILE @@FETCH_STATUS = 0 BEGIN
                Insert into Detalle_Produccion (IdProduccion, IdProducto, IdMateriaPrima, CantidadMPUsada)
                    values (@IdProduccion, @IdProducto, @IdMateriaPrima, @CantidadMPUsada)
 
                EXEC Agrega_Movimiento_Inventario
                @TipoMovimiento = 'Salida por produccion',
                @IdProduccion = @IdProduccion,
                @IdProducto = @IdMateriaPrima,
                @IdSucursal = @IdSucursal,
                @Cantidad = @CantidadMPUsada,
                @SelectFinal = 0,
                @IdUsuario = @IdUsuario,
                @Error = @Error OUTPUT
 
                IF @Error IS NOT null BEGIN
                    IF @@TRANCOUNT > 0
                        ROLLBACK TRAN
 
                    SET @Error = 'Agrega_Movimiento_Inventario: ' + @Error
 
                    IF @SelectFinal = 1 OR @SelectFinal IS NULL
                        SELECT @Error Error
                    RETURN
                END
 
                FETCH NEXT FROM CursorDetalleProduccion INTO @IdProducto, @IdMateriaPrima, @CantidadMPUsada
            END
 
            SET @IdProducto = (Select DISTINCT (IdProducto) from @TablaDetalleProduccion)
            EXEC Agrega_Movimiento_Inventario
            @TipoMovimiento = 'Entrada por produccion',
            @IdProduccion = @IdProduccion,
            @IdProducto = @IdProducto,
            @IdSucursal = @IdSucursal,
            @Cantidad = @CantidadProducida,
            @SelectFinal = 0,
            @IdUsuario = @IdUsuario,
            @Error = @Error OUT
 
            IF @Error IS NOT NULL BEGIN
                IF @@TRANCOUNT > 0
                    ROLLBACK TRAN
 
                SET @Error = 'Agrega_Movimiento_Inventario: ' + @Error
 
                IF @SelectFinal = 1 OR @SelectFinal IS NULL
                    SELECT @Error Error
                RETURN
            END
 
        COMMIT TRAN
 
        SET @Error = (SELECT ERROR_PROCEDURE() + ' ' + ERROR_MESSAGE())
 
        IF @SelectFinal = 1 OR @SelectFinal IS NULL
            SELECT @Error Error
    END TRY
 
    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK TRAN
 
        SET @Error = (SELECT ERROR_PROCEDURE() + ' ' + ERROR_MESSAGE())
 
        IF @SelectFinal = 1 OR @SelectFinal IS NULL
            SELECT @Error Error
    END CATCH
END

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CREATE PROCEDURE Registrar_Detalle_Venta
@NumeroRemision int,
@IdProducto int,
@Cantidad decimal (16,2),
@Descuento decimal (5,2),
@Importe decimal (16,2),
@MetodoEntrega varchar (60),
@SelectFinal bit = null,
@Error varchar(200) OUT
AS
BEGIN
    BEGIN TRY
        Insert into Detalle_Venta values (@NumeroRemision, @IdProducto, @Cantidad, @Descuento, @Importe, @MetodoEntrega)
        SET @Error = ERROR_PROCEDURE() + ' ' + ERROR_MESSAGE()
        IF @SelectFinal = 1 OR @SelectFinal IS NULL
            SELECT @Error Error
    END TRY
 
    BEGIN CATCH
        SET @Error = ERROR_PROCEDURE() + ' ' + ERROR_MESSAGE()
        IF @SelectFinal = 1 OR @SelectFinal IS NULL
            SELECT @Error Error
    END CATCH
END
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder