none
Insert Trigger vs. Inserción masiva de registros RRS feed

  • Pregunta

  • Estimados:

    Tengo una tabla 'Productos' que además del ID (autoincremental) tiene un campo índice único ('CodigoUnico') en el cual debo agregar valores incrementales en caso de inserción masiva, o provistos por el usuario en caso de inserción puntual de registros.
    Mi idea fue resolver esto con un Trigger, que al momento de Insertar el registro, evaluara el valor del campo 'CodigoUnico' y en caso de ser 0, incrementara de 1 el valor máximo de la columna e hiciera el UPDATE del registro insertado.

    El trigger es este:

    [code]      

    ALTER TRIGGER [dbo].[Productos_INSERT]
       ON  [dbo].[Productos]
       AFTER INSERT
    AS 
    BEGIN
    SET NOCOUNT ON;

    DECLARE @RC int
    DECLARE @r_id int
    DECLARE @CodPub int
     /* obtengo ID de registro y valor del campo CodigoUnico */
    SELECT @r_id = id, @CodPub = CodigoUnico FROM inserted

    /* si el valor es menor que 1 ... */

    IF @CodPub < 1
    BEGIN

    /* incremento en 1 el valor máximo de la columna */

        SELECT @RC=MAX(CodigoUnico)+1 FROM Productos 

        if @RC < 10000000
        BEGIN

                /* si el valor es menor que x establezco el valor inicial  */

    SET @RC=10000000
    END

    /* establezco el valor de la columna en el registro recién insertado */

    UPDATE Productos SET CodigoUnico = @RC Where id = @r_id
    END
    END
    [/code]

    El tema es que funciona perfecto cuando agrego un registro por vez, pero cuando intento una inserción masiva mediante SQL tomando datos de otra tabla (y obviamente enviando 0 para el campo CodigoUnico) me devuelve error de inconsistencia en el índice.

    Me podrían dar una idea de cómo realizar lo mismo para una inserción masiva?
    muchas gracias
    saludos


    • Editado BGuidi viernes, 27 de mayo de 2016 18:44
    viernes, 27 de mayo de 2016 18:44

Respuestas

  • Saludos

    Mi pregunta es porque estas usando esto para una insercion masiva, esto se deberia de controlar por import export wizard, un etl (normalmente como SSIS de Microsoft, data stage, informatica, etc), o bulk copy que seria la mas normal cuando no es una tarea repetitiva y quieres algo rapido, creo que estas usando una herramienta no adecuada para esto

    Aqui toco la insercion por lotes

    Inserciones por lotes batch


    • Editado José De Alva martes, 31 de mayo de 2016 16:06 url-
    • Marcado como respuesta José De Alva jueves, 2 de junio de 2016 22:05
    lunes, 30 de mayo de 2016 22:31

Todas las respuestas

  • BGuidi,

    ¿En que momento discrimina el trigger si la inserción individual fue realizada por el usuario? Lo menciono porque el valor ingresado por el usuario será ignorado, de ser así, ¿no es mejor definir ese campo con la propiedad IDENTITY?

    Por otro lado, el error que obtienes es de esperar, en caso insistas en el uso del trigger puedes hacer lo siguiente:

    UPDATE p
    SET
          p.CodigoUnico = (SELECT MAX(CodigoUnico) + 1 FROM CodigoUnico)
    FROM
          inserted i
          INNER JOIN Productos p ON (p.id = i.id)

    • Propuesto como respuesta José De Alva martes, 31 de mayo de 2016 16:01
    viernes, 27 de mayo de 2016 19:26
  • Yo creo que así no funcionaría; con esa instrucción todos los registros insertados a la vez recibirían el mismo valor del código único (que por lo tanto ya no sería único). Lamentablemente, así a bote pronto no se me ocurre ninguna solución "elegante" (no considero elegante usar un cursor). Habría que pensarlo con más cuidado.
    • Propuesto como respuesta José De Alva martes, 31 de mayo de 2016 16:02
    viernes, 27 de mayo de 2016 19:55
  • Antes que nada muchas gracias por responder.
    El tema es que esa tabla recibe registros dados de alta a traves de un formulario, y en ese caso se obliga al usuario a ingresar valores de hasta 7 dígitos (9999999), pero también ingresan datos de otros orígenes en forma masiva, por lo que se determinó que en ese caso el valor del campo esté por encima de 10000000.

    Utilicé un Trigger porque supuse que aún en el caso de la inserción masiva se dispararía durante la inserción de cada fila, pero parece que me equivoqué.

    No tengo mucha experiencia con Triggers, pero evidentemente tu propuesta es mucho más elegante que la mía.
    Muchas gracias

    viernes, 27 de mayo de 2016 20:07
  • Muchas gracias por tu atención

    Si, pensé que el trigger se dispararía en cada inserción, aún en caso masivo, pero evidentemente no funciona así.

    Ahora estoy probando rellenar en la tabla que provee los datos, un campo con el valor necesario, de modo de aplicar la inserción masiva, pero llevo ya varias horas y no logro que funcione el Update del objeto DataAdapter (he probado ya unas 6 alternativas con datarow, dataset, datatable, etc. y nada funciona).
    Tendrías por allí algún ejemplo de uso efectivo?

    Muy amable de tu parte

    saludos

    viernes, 27 de mayo de 2016 20:10
  • Saludos

    No deberías de usar un trigger con una inserción masiva de por si pues esto afecta el performance de la inserción, lamentablemente lo mejor seria desactivar el trigger y llenar manualmente durante estos momento, podría tomar como que las entradas en null son aquellas causadas por inserciones masivas.

    viernes, 27 de mayo de 2016 20:43
  • Gracias por tu atención Enrique.

    Por el momento decidí suspender el trabajo con el trigger y rellenar previamente con los valores deseados la columna 'codigoUnico' de la tabla temporaria para luego sí aplicar la Query de inserción masiva.
    El problema es que llevo horas haciendo pruebas con SqlDataAdapter, DataSet, SqlCommand etc etc etc y no logro escribir físicamente los datos en la columna de la tabla temporaria.

    Sería posible que me indicaras algún ejemplo de cómo actualizar un campo de una tabla mediante esos objetos de acceso a datos? Realmente me está comiendo todo el tiempo que disponía para esto...

    gracias y saludos cordiales

    lunes, 30 de mayo de 2016 21:13
  • Saludos

    Mi pregunta es porque estas usando esto para una insercion masiva, esto se deberia de controlar por import export wizard, un etl (normalmente como SSIS de Microsoft, data stage, informatica, etc), o bulk copy que seria la mas normal cuando no es una tarea repetitiva y quieres algo rapido, creo que estas usando una herramienta no adecuada para esto

    Aqui toco la insercion por lotes

    Inserciones por lotes batch


    • Editado José De Alva martes, 31 de mayo de 2016 16:06 url-
    • Marcado como respuesta José De Alva jueves, 2 de junio de 2016 22:05
    lunes, 30 de mayo de 2016 22:31