none
Trigger After INSERT con uniqueidentifier como obter el valor RRS feed

  • Pregunta

  • Tengo una BD donde se sincronizan datos de un sistema GPS, quiero realizar un trigger para mover unos datos de una tabla a otra ya que una consulta con un Join o por una vista tarda demasiado en realizarse, por lo cual opte por insertar a otra tabla a travez del trigger, el problema que tengo es que la primary key es un uniqueidentifier por lo cual no tengo mucho conocimiento de como obtenerlo y manejarlo para insertar, les dejo mi trigger mas abajo, el tema es que no me esta funcionando, no se si este mal la forma en que lo estoy llamando, de la tabla INSERTED obtengo mi primary key de tipo uniqueidentifier como les decía, saludos.

    CREATE TRIGGER [dbo].[sincronizador]
       ON  [IC_ClientDB].[dbo].[navman_ic_api_activitylogreal]
       AFTER INSERT
    AS 
    BEGIN
    declare @marketID uniqueidentifier 

    SET NOCOUNT ON;

    SELECT @marketID = ActivityLogRealID FROM INSERTED 

    INSERT INTO [IC_ClientDB].[dbo].[navman_ic_api_busmenapps_historial]
               ([Latidud],[Longitud],[Locacion],[idUnidad],[NoEmpleado],[NoEconomico],[Fecha])
    SELECT
    A.Latitude,A.Longitude,A.Location,A.VehicleID,B.RawExtendedData,'',A.ReceivedDateTime
    FROM  [IC_ClientDB].[dbo].[navman_ic_api_activitylogreal] AS A
    INNER JOIN [IC_ClientDB].[dbo].[navman_ic_api_activitylogextn] AS B
    ON A.ActivityLogRealID = B.ActivityLogID
    WHERE A.ActivityLogRealID = @marketID
    AND A.EventSubTypeID = 11

    END

    lunes, 9 de abril de 2018 17:15

Respuestas

  • Hola Havo07:

    Me parece que tu problema no es el campo tipo UNIQUEIDENTIFIER sino la sentencia insert.

    create table EJEMPLO1 (id uniqueidentifier ,
    datos varchar(10))
    go
    
    create table EJEMPLOHISTORICO (id uniqueidentifier, datos varchar(10))
    go
    
    CREATE TRIGGER [DBO].[EJEMPLOTrigger]
    ON [DBO].[EJEMPLO1]
    AFTER INSERT
    
    AS 
    BEGIN
    
    declare @marketID uniqueidentifier
    select @marketID = ID from inserted;
    print @marketID
    	INSERT INTO EJEMPLOHISTORICO SELECT * FROM inserted
    END
    GO
    /* TRIGGER PARA LA INSERCCIÓN */
    
    INSERT INTO EJEMPLO1(id, datos)
    VALUES (NEWID(), 'EJEMPLO')
    
    

    No he utilizado tabla ni tus datos, pues los desconozco, pero si te fijas en el ejemplo, con dos columnas, lo ejecuta correctamente. El campo @marketID, es solo para mostrar el identificador unico.

    Saludos

    lunes, 9 de abril de 2018 19:18
  • Javi, tanto tu query como el de Hav, no tienen en cuenta lo que dice webJose, un trigger siempre debe tener en cuenta que pueden hacerse actualizaciones masivas de datos.  Y que el trigger solo se llamará una vez con la tabla inserted llena 

    en este caso se solventaría con un insert -select

    la sentencia en general sería

    dentro de tu trigger

    insert into tutabladestino (campo1,campo2,campo3)

    select campo1,campo2,campo3 from inserted where not exists(select 1 from tutabladestino where tutabladestino.campoclave=inserted.campoclave)

    no hay problema porque sea un unique identifier, si que tendrías problema si fuera un timestamp/rowversion porque simplemente esos no se pueden especificar o un identity por que tendrías que especificar la clausula set identity insert on. 


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 11 de abril de 2018 6:03
    Moderador
  • Hola Miguel:

    Tengo en cuenta lo que dices, pero creo que al ejemplo que yo le menciono es valido ¿no?

    Supongo que os lleva al huerto el igual, para el print, pero creo que funciona bien.

    Para verificarlo he ejecutado lo siguiente.

    Cree una tabla ejemplo03 y una ejemplo 04

    declare @iterador int = 0;
    while (@iterador<1000000)
    begin
    	INSERT INTO EJEMPLO3(id, datos)
    		VALUES (NEWID(), cast (@iterador as varchar))
    		set @iterador = @iterador + 1;
    end
    

    Llene las dos con los tropecientos ceros.

    Y en dos ventanas diferentes del managment, ejecute una insert sobre la tabla ejemplo1

    Al final ejemplo historico contiene todos los datos.

    No obstante, remarco, que vuestra puntualización me parece muy bien, y suma y mejora, porque, y supongo que mentalmente me llevo al huerto un poco el UNIQUEIDENTIFIER, y como has puesto, además, eso no evita que ya existiese el registro por yo que se la lógica de negocio, que hizo que....y si ya existía, y viene un loco que hace un bulkcopy sobre tropecientos millones, y perdi el historico.... :)

    Gracias







    miércoles, 11 de abril de 2018 6:59
  • Gracias Miguel:

    Si cuando me refería al print era eso.

    Dado que los que hacen el sql son mucho más finos que el que suscribe, esa parte solo coge (como dices el identificador que le parezca de la tabla inserted (1)), o tiene 1 millon de errores, try cacheados. quedando solo 1.

    Si te das cuenta en mi codigo solo lo imprimo, no lo utilizo para nada.

    Y definitivamente, los triggers son la mejor herramienta, para que tu creas que algo esta de pu...a ma...e y cuando pasa un tiempo, algo ha ocurrido.... y buscate la vida

    Saludos

    miércoles, 11 de abril de 2018 7:31

Todas las respuestas

  • Hola Havo07:

    Me parece que tu problema no es el campo tipo UNIQUEIDENTIFIER sino la sentencia insert.

    create table EJEMPLO1 (id uniqueidentifier ,
    datos varchar(10))
    go
    
    create table EJEMPLOHISTORICO (id uniqueidentifier, datos varchar(10))
    go
    
    CREATE TRIGGER [DBO].[EJEMPLOTrigger]
    ON [DBO].[EJEMPLO1]
    AFTER INSERT
    
    AS 
    BEGIN
    
    declare @marketID uniqueidentifier
    select @marketID = ID from inserted;
    print @marketID
    	INSERT INTO EJEMPLOHISTORICO SELECT * FROM inserted
    END
    GO
    /* TRIGGER PARA LA INSERCCIÓN */
    
    INSERT INTO EJEMPLO1(id, datos)
    VALUES (NEWID(), 'EJEMPLO')
    
    

    No he utilizado tabla ni tus datos, pues los desconozco, pero si te fijas en el ejemplo, con dos columnas, lo ejecuta correctamente. El campo @marketID, es solo para mostrar el identificador unico.

    Saludos

    lunes, 9 de abril de 2018 19:18
  • Havo07, también le recuerdo que en un trigger, la tabla INSERTED y DELETED pueden tener más de un registro.  Usted programó su trigger como si solamente hubiera un registro en INSERTED.  Uno siempre debe programar triggers que soporten múltiples filas.

    Jose R. MCP
    Code Samples

    martes, 10 de abril de 2018 23:42
  • Javi, tanto tu query como el de Hav, no tienen en cuenta lo que dice webJose, un trigger siempre debe tener en cuenta que pueden hacerse actualizaciones masivas de datos.  Y que el trigger solo se llamará una vez con la tabla inserted llena 

    en este caso se solventaría con un insert -select

    la sentencia en general sería

    dentro de tu trigger

    insert into tutabladestino (campo1,campo2,campo3)

    select campo1,campo2,campo3 from inserted where not exists(select 1 from tutabladestino where tutabladestino.campoclave=inserted.campoclave)

    no hay problema porque sea un unique identifier, si que tendrías problema si fuera un timestamp/rowversion porque simplemente esos no se pueden especificar o un identity por que tendrías que especificar la clausula set identity insert on. 


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 11 de abril de 2018 6:03
    Moderador
  • Hola Miguel:

    Tengo en cuenta lo que dices, pero creo que al ejemplo que yo le menciono es valido ¿no?

    Supongo que os lleva al huerto el igual, para el print, pero creo que funciona bien.

    Para verificarlo he ejecutado lo siguiente.

    Cree una tabla ejemplo03 y una ejemplo 04

    declare @iterador int = 0;
    while (@iterador<1000000)
    begin
    	INSERT INTO EJEMPLO3(id, datos)
    		VALUES (NEWID(), cast (@iterador as varchar))
    		set @iterador = @iterador + 1;
    end
    

    Llene las dos con los tropecientos ceros.

    Y en dos ventanas diferentes del managment, ejecute una insert sobre la tabla ejemplo1

    Al final ejemplo historico contiene todos los datos.

    No obstante, remarco, que vuestra puntualización me parece muy bien, y suma y mejora, porque, y supongo que mentalmente me llevo al huerto un poco el UNIQUEIDENTIFIER, y como has puesto, además, eso no evita que ya existiese el registro por yo que se la lógica de negocio, que hizo que....y si ya existía, y viene un loco que hace un bulkcopy sobre tropecientos millones, y perdi el historico.... :)

    Gracias







    miércoles, 11 de abril de 2018 6:59
  • lo que está mal en tu código es esto 

    declare @marketID uniqueidentifier
    select @marketID = ID from inserted;

    ese select tomará aleatoriamente 1 registro, y ese id hay que mantenerlo en la tabla destino.

    De todas formas entiendo tu punto, a mi no me gustan los triggers, me parece que ocultan información y mucho menos me gustan las claves con uniqueidentifier, son un poco aberración particularmente si es el índice clustered. Lo que pasa es que algunas veces... simplemente es así. 


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 11 de abril de 2018 7:21
    Moderador
  • Gracias Miguel:

    Si cuando me refería al print era eso.

    Dado que los que hacen el sql son mucho más finos que el que suscribe, esa parte solo coge (como dices el identificador que le parezca de la tabla inserted (1)), o tiene 1 millon de errores, try cacheados. quedando solo 1.

    Si te das cuenta en mi codigo solo lo imprimo, no lo utilizo para nada.

    Y definitivamente, los triggers son la mejor herramienta, para que tu creas que algo esta de pu...a ma...e y cuando pasa un tiempo, algo ha ocurrido.... y buscate la vida

    Saludos

    miércoles, 11 de abril de 2018 7:31