2009-08-04 42 views
5

no es un duplicado de my previous question¿Cómo obtener la última inserción/actualización/eliminación de fecha y hora en Sql Server 2005?

¿Hay alguna manera de obtener la última fecha y hora cuando una tabla/base de datos tenía una inserción/actualización/eliminación en Sql Server 2005? Preferiblemente sin crear disparadores ..

Sé que cuando necesite la última actualización por fila, necesita desencadenantes. Pero no estoy seguro si son necesarios cuando solo quieres obtener la última actualización para toda la tabla.

+1

La respuesta que aceptó es engañoso en el mejor. –

Respuesta

8

usted puede fácilmente tener la última insertados/fechas Actualizado/eliminados de la siguiente manera:

CREATE FUNCTIOn fn_TablesLastUpdateDate(@Date NVARCHAR(20)) 

RETURNS @table TABLE(TableName NVARCHAR(40), LastUpdated Datetime) 

AS 

BEGIN 


IF(@Date='') OR (@Date Is Null) OR (@Date='0') 

    BEGIN 
     INSERT INTO @table 
     SELECT TOP 100 PERCENT TABLENAME,LASTUPDATED FROM 
     (
      SELECT B.NAME AS 'TABLENAME', MAX(STATS_DATE (ID,INDID)) AS LASTUPDATED 
      FROM SYS.SYSINDEXES AS A 
        INNER JOIN SYS.OBJECTS AS B ON A.ID = B.OBJECT_ID 
      WHERE B.TYPE = 'U' AND STATS_DATE (ID,INDID) IS NOT NULL 
      GROUP BY B.NAME 
     ) AS A 
     ORDER BY LASTUPDATED DESC 
    END 
ELSE 

    BEGIN 
     INSERT INTO @table 
     SELECT TOP 100 PERCENT TABLENAME,LASTUPDATED FROM 
     (
      SELECT B.NAME AS 'TABLENAME', MAX(STATS_DATE (ID,INDID)) AS LASTUPDATED, 
        CONVERT(VARCHAR, MAX(STATS_DATE (ID,INDID)), 103) as Date 
      FROM SYS.SYSINDEXES AS A 
        INNER JOIN SYS.OBJECTS AS B ON A.ID = B.OBJECT_ID 
      WHERE B.TYPE = 'U' AND STATS_DATE (ID,INDID) IS NOT NULL 
      GROUP BY B.NAME 
     ) AS A 
     WHERE [email protected] 
     ORDER BY LASTUPDATED DESC 
    END 
RETURN 

END 



-- SELECT * from fn_TablesLastUpdateDate('06/11/2012') 
+0

Puede ejecutar la instrucción Select interna si no tiene permisos de administrador o elevados y todavía obtiene sus resultados. Gran solución –

+1

Mayeb Me perdí algo pero en SQL-SERVER 2008 esto no muestra ningún cambio en el 'LASTUPDATED' si las filas se insertaron/actualizaron/eliminaron. Solo cuando se modificó la estructura de la tabla (se agregaron columnas/índices, etc.). ¿Es eso lo que el OP pretendía? – ZigiZ

+0

@ZigiZ: Tal vez lo confunde con la columna 'sys.objects.modify_date', que para las tablas muestra la última fecha de cambio de la estructura. Los valores en la columna 'LASTUPDATED' en este código se basan en los resultados de la función [' STATS_DATE'] (http://technet.microsoft.com/en-us/library/ms190330.aspx "STATS_DATE (Transact-SQL)) "). –

2

Dado que no hay respuestas, sin embargo, aquí están mis 2 centavos:

  • Para Insertar, me gustaría utilizar un campo DateTime con valor predeterminado GETDATE()
  • Para Update, me gustaría utilizar también un DateTime campo modificado por disparador cada vez que hay una actualización.
  • Para Eliminar, el registro no estará disponible, por lo que no puede consultarlo.

Pensé en utilizar las marcas de tiempo para evitar desencadenantes, pero no puede convertir la marca de tiempo en fecha y hora.

EDIT: O tal vez usted puede utilizar un "metatabla" donde en los disparadores que se ahorrará el cambio de fechas

CREATE TABLE metatable (
table_name VARCHAR(40) NOT NULL PRIMARY KEY, 
last_insert DATETIME NOT NULL, 
last_update DATETIME NOT NULL, 
last_delete DATETIME NOT NULL 
) 

INSERT metatable VALUES ('table1', GETDATE(), GETDATE(), GETDATE()) 

CREATE TRIGGER trg_table1_ins ON table1 FOR INSERT AS BEGIN 
    UPDATE metatable SET last_insert = GETDATE() WHERE table_name = 'table1' 
END 

CREATE TRIGGER trg_table1_upd ON table1 FOR UPDATE AS BEGIN 
    UPDATE metatable SET last_update = GETDATE() WHERE table_name = 'table1' 
END 

CREATE TRIGGER trg_table1_del ON table1 FOR DELETE AS BEGIN 
    UPDATE metatable SET last_delete = GETDATE() WHERE table_name = 'table1' 
END 

espero que sea útil

+1

solo ten cuidado con el bloqueo. Si tiene algunas transacciones ejecutándose al mismo tiempo que alteran la misma tabla (filas diferentes que no causarían bloqueo), tendrán que esperar su turno para actualizar la fila de una tabla de registro para esa tabla. –

+0

Sí, tienes razón, ¿podrías modificar el código para que refleje los cambios que mencionaste? No me molestará ese –

1

sin factores desencadenantes: usted podría tener un LastChgDate columna en la tabla, y configurarlo cuando inserta/actualiza/elimina una fila. Tendría que "eliminar" usando una columna de estado establecida en "D" o algo así. Coloque un índice en esta columna y seleccione MAX() para ver cuándo se realizó un cambio.

+0

solo para que quede claro, LastChgDate sería un tipo de fecha y hora y tendría que configurarlo para GETDATE() en cada INSERT/UPDATE. Además, los "DELETE" se manejarían como una ACTUALIZACIÓN con un cambio de estado a "D", y luego podrían consultarse para la última hora de cambio. –

+0

yendo y viniendo entre una tabla de registro y la columna de fecha y hora en la tabla real parece engorroso –

1

Bueno, podría mantener una columna con un "LastUpdateDate" que se establece en la fecha/hora actual del servidor en cualquier inserción o actualización. Luego, simplemente puede consultar la fila con el último LastUpdateDate.

5

Como muestran las dos respuestas anteriores, en realidad no hay ninguna función incorporada en SQL Server que esté disponible para sus necesidades.

Existen un montón de vistas de administración dinámica que le pueden indicar algunos de sus puntos de interés, p. sys.dm_db_index_usage_stats, que le indica cuándo un índice determinado ha tenido su última búsqueda o actualización.

Pero realmente no hay nada en la caja per se que pueda aprovechar para obtener toda la información que está buscando, realmente tiene que hacerlo usted mismo, agregando, p. campos de fecha y hora a sus tablas y llenarlos con desencadenantes.

Lo siento, no puedo darle ninguna mejor noticia, así es como es ahora.

En SQL Server 2008, tiene nuevas características adicionales, que podrían cubrir algunas de sus necesidades - echa un vistazo a:

Marc

2

Durante corta períodos (desde el inicio del servidor) usted verifica sys.dm_db_index_usage_stats last_user_update column. Pero como esto solo cuenta actualizaciones desde el inicio del servidor, no se puede usar durante un largo período de tiempo.

Durante largos períodos de tiempo, si la tabla no es grande, su aplicación puede almacenar la tabla CHECKSUM_AGG(ALL). Solo necesita volver a calcular esto una vez, al inicio de la aplicación, y compararlo con el valor almacenado anteriormente. Además, la aplicación puede detectar cambios utilizando el DMV. En el cierre de la aplicación, debe almacenar la suma de comprobación de la tabla actual.

0

¡Simple! Primero agregue una columna "LastUpdated". Déle el valor predeterminado de GetDate(). Esto se encargará de las declaraciones de inserción. En segundo lugar, agregue un activador de actualización que actualice LastUpdated a GetDate(). Las actualizaciones ahora están cubiertas. Finalmente, agregue un campo bit/booleano IsDeleted con el valor predeterminado 0. Si un usuario desea eliminar una fila, voltee el bit. Como cuando "borra" una fila, en realidad está actualizando el campo IsDeleted (y, por lo tanto, está utilizando una acción Update), las eliminaciones ahora tienen marca de tiempo.

Para obtener la actividad más reciente sobre la mesa: sólo a obtener la marca de tiempo:

SELECT MAX(LastUpdated) FROM MyTable 

Para obtener más información:

SELECT MAX(LastUpdated), ID /*or whatever you need to know*/ FROM MyTable 
+0

Por supuesto, si agrega el campo de bit ISDeleted, deberá volver a hacer todo su código para asegurarse de que los registros eliminados no se utilicen en el consultas. – HLGEM

+0

De acuerdo, no va a ser sin dolor, pero mostrará la última actividad en la mesa, sin importar de qué se trate. – Pulsehead

1

me gustaría añadir el seguimiento de cambios a la mezcla - como opuesto a la Captura de datos modificados, no es una función exclusiva de Enterprise.

Lea acerca de esto en http://msdn.microsoft.com/en-us/library/cc280462.aspx

similares a sys.dm_db_index_usage_stats, los datos no están allí para siempre (aunque sobrevive reiniciado el servidor y es configurable) y tendrá que extraer y conservar el pedazo particular de la información que está buscando.

MDD

12
SELECT t.name, 
     user_seeks, 
     user_scans, 
     user_lookups, 
     user_updates, 
     last_user_seek, 
     last_user_scan, 
     last_user_lookup, 
     last_user_update 
FROM sys.dm_db_index_usage_stats i 
     JOIN sys.tables t 
     ON (t.object_id = i.object_id) 
WHERE database_id = DB_ID() 
Cuestiones relacionadas