SQL TRANSACTIONS

1

A query, I have a procedure with transaction handling, in which several INSERT must be executed, as I do to know in which INSERT I failed the procedure in such a way that I can show in the RAISERROR message something like "error to insert the document XXXXXXXXX in the JOURNAL "

I have ignored the declaration of variables, etc., etc. in order to graph what is intended to achieve.

ALTER procedure PROCESA_FACTURA
(@PROVEEDOR VARCHAR(20),
 @DOCUMENTO VARCHAR(50),
 @TIPO VARCHAR(3))
AS
BEGIN

    SET NOCOUNT ON;
    SET LANGUAGE SPANISH;   

    BEGIN TRANSACTION 

    BEGIN TRY

        -- ASIENTO_DE_DIARIO
        INSERT INTO ASIENTO_DE_DIARIO
        (ASIENTO,PAQUETE,TIPO_ASIENTO,FECHA,CONTABILIDAD,ORIGEN,CLASE_ASIENTO,
            TOTAL_DEBITO_LOC,TOTAL_DEBITO_DOL,TOTAL_CREDITO_LOC,TOTAL_CREDITO_DOL,
            ULTIMO_USUARIO,FECHA_ULT_MODIF,MARCADO,NOTAS,TOTAL_CONTROL_LOC,TOTAL_CONTROL_DOL,
            USUARIO_CREACION,FECHA_CREACION,DEPENDENCIA)
        SELECT 
        @ASIENTO, @PAQUETE, @TIPO_ASIENTO, @FECHA, @CONTABILIDAD, @ORIGEN, @CLASE_ASIENTO,
        @TOTAL_DEBITO_LOC, @TOTAL_DEBITO_DOL, @TOTAL_CREDITO_LOC, @TOTAL_CREDITO_DOL,
        @ULTIMO_USUARIO, @FECHA_ULT_MODIF, @MARCADO, @NOTAS_TEMP, @TOTAL_CONTROL_LOC, @TOTAL_CONTROL_DOL,
        @USUARIO_CREACION, @FECHA_CREACION, @DEPENDENCIA;


        -- DIARIO
        INSERT INTO DIARIO
        (ASIENTO,CONSECUTIVO,NIT,CENTRO_COSTO,CUENTA_CONTABLE,FUENTE,REFERENCIA,
            DEBITO_LOCAL,DEBITO_DOLAR,CREDITO_LOCAL,CREDITO_DOLAR,DEBITO_UNIDADES,CREDITO_UNIDADES,
            TIPO_CAMBIO,BASE_LOCAL,BASE_DOLAR,PROYECTO,FASE,PROCESO_REBATE)
        SELECT
        @ASIENTO,@CONSECUTIVO,@NIT,@CENTRO_COSTO,@CUENTA_CONTABLE,@FUENTE,@REFERENCIA,
        @DEBITO_LOCAL,@DEBITO_DOLAR,@CREDITO_LOCAL,@CREDITO_DOLAR,@DEBITO_UNIDADES,@CREDITO_UNIDADES,
        @TIPO_CAMBIO,@BASE_LOCAL,@BASE_DOLAR,@PROYECTO,@FASE,@PROCESO_REBATE;

        -- DIARIO2
        INSERT INTO DIARIO2
        (ASIENTO,CONSECUTIVO,NIT,CENTRO_COSTO,CUENTA_CONTABLE,FUENTE,REFERENCIA,
            DEBITO_LOCAL,DEBITO_DOLAR,CREDITO_LOCAL,CREDITO_DOLAR,DEBITO_UNIDADES,CREDITO_UNIDADES,
            TIPO_CAMBIO,BASE_LOCAL,BASE_DOLAR,PROYECTO,FASE,PROCESO_REBATE)
        SELECT
        @ASIENTO,@CONSECUTIVO,@NIT,@CENTRO_COSTO,@CUENTA_CONTABLE,@FUENTE,@REFERENCIA,
        @DEBITO_LOCAL,@DEBITO_DOLAR,@CREDITO_LOCAL,@CREDITO_DOLAR,@DEBITO_UNIDADES,@CREDITO_UNIDADES,
        @TIPO_CAMBIO,@BASE_LOCAL,@BASE_DOLAR,@PROYECTO,@FASE,@PROCESO_REBATE;


        -- MAYOR
        INSERT INTO MAYOR
        (ASIENTO,CONSECUTIVO,NIT,CENTRO_COSTO,CUENTA_CONTABLE,FUENTE,REFERENCIA,
            DEBITO_LOCAL,DEBITO_DOLAR,CREDITO_LOCAL,CREDITO_DOLAR,DEBITO_UNIDADES,CREDITO_UNIDADES,
            TIPO_CAMBIO,BASE_LOCAL,BASE_DOLAR,PROYECTO,FASE,PROCESO_REBATE)
        SELECT
        @ASIENTO,@CONSECUTIVO,@NIT,@CENTRO_COSTO,@CUENTA_CONTABLE,@FUENTE,@REFERENCIA,
        @DEBITO_LOCAL,@DEBITO_DOLAR,@CREDITO_LOCAL,@CREDITO_DOLAR,@DEBITO_UNIDADES,@CREDITO_UNIDADES,
        @TIPO_CAMBIO,@BASE_LOCAL,@BASE_DOLAR,@PROYECTO,@FASE,@PROCESO_REBATE;
        --END


        -- GRABA BITACORA
        INSERT INTO BITACORA
            (TIPO_CARGA,PROVEEDOR,FECHA_DOCUMENTO,TIPO_DOCUMENTO,DOCUMENTO,CONDICION_PAGO,SUBTOTAL,IMPUESTO,
             MONTO,MONEDA,TIPO_CAMB_DOCUM,TIPO_CAMB_TVTA,TIPO_CAMB_TCOM,MONTO_RETENCION,MONTO_DETRACCION,FECHA_PROCESO)
            SELECT
            'CARGA_XML',@PROVEEDOR,@FECHA_DOCUMENTO,@TIPO,@DOCUMENTO,@CONDICION_PAGO,@SUBTOTAL,@IMPUESTO1,
            @MONTO,@MONEDA,@TVTA,@TVTA,@TCOM,@MONTO_RETENCION, @MONTO_DETRACCION,GETDATE();

        COMMIT TRANSACTION 

    END TRY

    BEGIN CATCH

        SET @strMsg = 'CARGA_XML_PROVEEDORES.   Se ha producido un error!.   No se pudo Grabar la información. '
                    +'Tipo Documento: '+ @DOCUMENTO + '  '
                    +'Documento: '+ @TIPO + '  '
        RAISERROR (@strMsg,16,1);           


    END CATCH


END
    
asked by Max Cabanillas 26.01.2018 в 21:02
source

2 answers

0

A simple way is by declaring a variable and completing it before each insert. For example, at the beginning of your code:

DECLARE @Operacion VARCHAR(255)

And before each insert:

 SELECT @Operacion = 'Insertar en ASIENTO_DE_DIARIO'
 -- ASIENTO_DE_DIARIO
    INSERT INTO ASIENTO_DE_DIARIO
    (ASIENTO,PAQUETE,TIPO_ASIENTO,FECHA,CONTABILIDAD,ORIGEN,CLASE_ASIENTO,
        TOTAL_DEBITO_LOC,TOTAL_DEBITO_DOL,TOTAL_CREDITO_LOC,TOTAL_CREDITO_DOL,
        ULTIMO_USUARIO,FECHA_ULT_MODIF,MARCADO,NOTAS,TOTAL_CONTROL_LOC,TOTAL_CONTROL_DOL,
        USUARIO_CREACION,FECHA_CREACION,DEPENDENCIA)
    SELECT 
    @ASIENTO, @PAQUETE, @TIPO_ASIENTO, @FECHA, @CONTABILIDAD, @ORIGEN, @CLASE_ASIENTO,
    @TOTAL_DEBITO_LOC, @TOTAL_DEBITO_DOL, @TOTAL_CREDITO_LOC, @TOTAL_CREDITO_DOL,
    @ULTIMO_USUARIO, @FECHA_ULT_MODIF, @MARCADO, @NOTAS_TEMP, @TOTAL_CONTROL_LOC, @TOTAL_CONTROL_DOL,
    @USUARIO_CREACION, @FECHA_CREACION, @DEPENDENCIA;

and finally in the block CATCH() we add the variable @Operacion to the final message:

SET @strMsg = 'CARGA_XML_PROVEEDORES. Se ha producido un error al ' + @Operacion + ' !.   No se pudo Grabar la información. '
                +'Tipo Documento: '+ @DOCUMENTO + '  '
                +'Documento: '+ @TIPO + '  '
    RAISERROR (@strMsg,16,1);  

Another way, I can not think of it, it would be necessary to investigate if it is possible to automatically recover the name of the table where the error occurred, which I doubt a little.

    
answered by 26.01.2018 в 22:07
0

Ideally, you should do it with the ERROR_MESSAGE() function and make use of it within your CATCH block. That function returns a VARCHAR with the detail of the failure, including the information of the data that you are inserting.

In addition to also using the function ERROR_LINE() that will show you on which line the problem was caused, the number of the error with ERROR_NUMBER() including the name of the Stored Procedure where it occurred the fault using ERROR_PROCEDURE() .

Assuming that you store the errors caused in a log, the code would look something like this:

BEGIN TRY
    BEGIN TRANSACTION
    -- Todas las operaciones requeridas, INSERT, DELETE, UPDATE, DELETE, SELECT etc.
   COMMIT
END TRY
BEGIN CATCH
    INSERT INTO LOG
    SELECT ERROR_NUMBER(),  -- Número de error
           ERROR_LINE(),    -- Número de línea
           ERROR_MESSAGE(), -- Mensaje de error
           ERROR_PROCEDURE() -- Nombre del SP donde se originó el error
           GETDATE()        -- Fecha y hora en que originó el error

    IF @@TRANCOUNT > 0      
    BEGIN      
        ROLLBACK TRANSACTION;      
    END 
END CATCH

Something I noticed, is that in case of failure you do not have the ROLLBACK of your transaction and therefore it would stay "alive" blocking the objects that are involved within it.

    
answered by 26.01.2018 в 23:00