none
Cómo saber que fila de mi base de datos fue actualizada? RRS feed

  • Pregunta

  • Buen día a todos, antes que nada quiero decir que no soy dba y conozco de SQL Server a nivel de programador. Hace unos días me preguntaron si podía enviar correos electrónicos cada vez que se actualicen los registros de una tabla de mi base de datos. La verdad no sabía si tal cosa se podía o no y pues después de buscar muy poco en realidad di con la solución. Sin embargo no satisface del todo la necesidad, ya que si bien el email se envía cada vez que alguien actualiza algo en la tabla, no me dice que registro es el que se actualizó. Por ello es que recurro a ustedes el día de hoy para saber si es posible identificar ello. El trigger que encontré es muy básico aún se los dejo para ver si me pueden orientar más con este tema. Desde ya muchas gracias

    CREATE TRIGGER Gestor_Admin
    ON Gestores
    AFTER INSERT, UPDATE, DELETE 
    AS 
       EXEC msdb.dbo.sp_send_dbmail 
       	@profile_name = 'Administrador', 
            @recipients = 'micorreoelectronico@gmail.com' , 
            @body = 'Actualizaron Datos', 
            @subject = 'Sus registros han sido modificados' 
    GO

    domingo, 25 de septiembre de 2016 20:29

Respuestas

  • es posible además del ID capturar el valor de alguna otra columna?

    Las que quieras, no tienes más que ponerlas en la Select exactamente igual que si estuvieras haciendo un Select sobre una tabla corriente en un programa corriente, en lugar de hacerlo en un trigger. Por ejemplo, una manera sencilla es esta:

    @body = 'Actualizaron Datos'+(select top 1 cast(ID as varchar(10))+' '+Nombre+' '+Apellido as Texto from inserted), 
           

    Obviamente ese ejemplo presume que las columnas se llaman "Nombre" y "Apellido", y que las quieres separadas por un espacio en blanco.

    • Marcado como respuesta Carlos Sk martes, 27 de septiembre de 2016 14:08
    lunes, 26 de septiembre de 2016 19:20
  • Muchas gracias por tu respuesta. Podría indicarme la manera correcta de capturar los ID que menciona para poder concatenarlos se lo agradecería mucho

    En el caso más simple podrías hacer algo así:

    CREATE TRIGGER Gestor_Admin
    ON Gestores
    AFTER INSERT, UPDATE, DELETE 
    AS 
       EXEC msdb.dbo.sp_send_dbmail 
       	@profile_name = 'Administrador', 
            @recipients = 'micorreoelectronico@gmail.com' , 
            @body = 'Actualizaron Datos'+(select top 1 cast(ID as varchar(10)) as ID from inserted), 
            @subject = 'Sus registros han sido modificados' 
    GO

    Sin embargo, nótese que esto solo devuelve el ID de la primera fila modificada. Si modificas muchos registros de golpe con una sola sentencia, el trigger se dispara una sola vez y le llegan todos juntos. Ahí tendrás que tomar una decisión sobre cómo quieres tratarlos, por ejemplo concatenar todos los ID y enviarlos en un solo mensaje, o hacer un bucle y enviar un mensaje por cada registro. En cualquiera de los casos hay que programarlo y hacer el correspondiente bucle, no es algo que "salga solo" como en el ejemplo sencillo que te puse. Ten también presente el caso del Deleted. Podrías tratarlo con un IF en el mismo trigger, o hacer un trigger por separado con el AFTER DELETE, en lugar de juntarlo con el INSERT y UPDATE tal como tienes ahora.

    • Marcado como respuesta Carlos Sk lunes, 26 de septiembre de 2016 18:36
    lunes, 26 de septiembre de 2016 6:45

Todas las respuestas

  • Fíjate que el trigger que has hecho tiene un parámetro llamado @body que sirve para escribir el contenido del correo. En ese string puedes concatenarle los datos que consideres oportunos para indicar cuál es el registro que se modificó. Lógicamente, depende de cada tabla la elección de esos datos, por ejemplo, puede haber tablas en las que tengas un campo ID que sea un identificador único y te interese adjuntar ese ID en el mensaje, pero a lo mejor en otra tabla lo que tienes que sacar es el nombre y los apellidos, o la matrícula, o lo que sea que estés usando en esa tabla.

    Para extraer un dato de la tabla, lo que hay que saber es que al trigger le llegan dos pseudo-tablas llamadas INSERTED y DELETED. En la tabla INSERTED encontrarás el registro (o registros) que se insertó, con un select sobre ella puedes extraer el ID o cualesquiera otros campos que te interesen. Similarmente, si fue un borrado en la tabla DELETED te llega el registro que se borró (o los registros que se borraron, si se borraron varios de golpe con una sola instrucción delete). Y so es un UPDATE, te llegan las dos tablas inserted y deleted, con el dato nuevo y el antiguo respectivamente.

    domingo, 25 de septiembre de 2016 21:13
  • Muchas gracias por tu respuesta. Podría indicarme la manera correcta de capturar los ID que menciona para poder concatenarlos se lo agradecería mucho
    domingo, 25 de septiembre de 2016 21:21
  • Carlos te recomiendo estudiar las tablas auxiliares inserted y deleted

    https://msdn.microsoft.com/es-cl/library/ms191300.aspx

    lunes, 26 de septiembre de 2016 4:34
  • Muchas gracias por tu respuesta. Podría indicarme la manera correcta de capturar los ID que menciona para poder concatenarlos se lo agradecería mucho

    En el caso más simple podrías hacer algo así:

    CREATE TRIGGER Gestor_Admin
    ON Gestores
    AFTER INSERT, UPDATE, DELETE 
    AS 
       EXEC msdb.dbo.sp_send_dbmail 
       	@profile_name = 'Administrador', 
            @recipients = 'micorreoelectronico@gmail.com' , 
            @body = 'Actualizaron Datos'+(select top 1 cast(ID as varchar(10)) as ID from inserted), 
            @subject = 'Sus registros han sido modificados' 
    GO

    Sin embargo, nótese que esto solo devuelve el ID de la primera fila modificada. Si modificas muchos registros de golpe con una sola sentencia, el trigger se dispara una sola vez y le llegan todos juntos. Ahí tendrás que tomar una decisión sobre cómo quieres tratarlos, por ejemplo concatenar todos los ID y enviarlos en un solo mensaje, o hacer un bucle y enviar un mensaje por cada registro. En cualquiera de los casos hay que programarlo y hacer el correspondiente bucle, no es algo que "salga solo" como en el ejemplo sencillo que te puse. Ten también presente el caso del Deleted. Podrías tratarlo con un IF en el mismo trigger, o hacer un trigger por separado con el AFTER DELETE, en lugar de juntarlo con el INSERT y UPDATE tal como tienes ahora.

    • Marcado como respuesta Carlos Sk lunes, 26 de septiembre de 2016 18:36
    lunes, 26 de septiembre de 2016 6:45
  • Ese ejemplo básico me servirá de mucho. Solamente una consulta adicional, es posible además del ID capturar el valor de alguna otra columna? Gracias
    lunes, 26 de septiembre de 2016 18:38
  • es posible además del ID capturar el valor de alguna otra columna?

    Las que quieras, no tienes más que ponerlas en la Select exactamente igual que si estuvieras haciendo un Select sobre una tabla corriente en un programa corriente, en lugar de hacerlo en un trigger. Por ejemplo, una manera sencilla es esta:

    @body = 'Actualizaron Datos'+(select top 1 cast(ID as varchar(10))+' '+Nombre+' '+Apellido as Texto from inserted), 
           

    Obviamente ese ejemplo presume que las columnas se llaman "Nombre" y "Apellido", y que las quieres separadas por un espacio en blanco.

    • Marcado como respuesta Carlos Sk martes, 27 de septiembre de 2016 14:08
    lunes, 26 de septiembre de 2016 19:20
  • Muchísimas gracias de verdad me ha servido mucho.
    martes, 27 de septiembre de 2016 14:09