2009-08-04 12 views
5

non un duplicato di my previous questionCome arrivare ultimo inserimento/aggiornamento/cancellazione datetime in SQL Server 2005?

C'è un modo per ottenere l'ultima datetime quando una tabella/base di dati ha avuto un inserimento/aggiornamento/delete su SQL Server 2005? Preferibilmente senza creare trigger ..

So che quando è necessario l'ultimo aggiornamento per riga, è necessario trigger. Ma non sono sicuro che siano necessari quando si desidera ottenere l'ultimo aggiornamento per l'intero tavolo.

+1

La risposta è stata accettata è fuorviante al meglio. –

risposta

8

si può ottenere facilmente le Ultimi inseriti/aggiornati date/eliminata come segue:

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

È possibile eseguire l'istruzione Select interna se non si dispone dell'autorizzazione amministrativa o elevata e si ottengono comunque i risultati. Ottima soluzione. –

+1

Mayeb Mi sono perso qualcosa ma in SQL-SERVER 2008 questo non mostra alcuna modifica in "LASTUPDATED" se le righe sono state inserite/aggiornate/cancellate. Solo quando la struttura della tabella è stata modificata (colonne/indici aggiunti ecc.). è questo ciò che l'OP intendeva? – ZigiZ

+0

@ZigiZ: Forse lo stai confondendo con la colonna 'sys.objects.modify_date', che per le tabelle mostra l'ultima data di modifica della struttura. I valori nella colonna 'LASTUPDATED' in questo codice sono basati sui risultati della funzione [' STATS_DATE'] (http://technet.microsoft.com/en-us/library/ms190330.aspx "STATS_DATE (Transact-SQL) "). –

2

Dato non ci sono risposte ancora, qui sono i miei 2 centesimi:

  • per l'inserimento, vorrei utilizzare un campo datetime con GETDATE valore di default()
  • Per Update, vorrei utilizzare anche una DateTime campo modificato dal trigger ogni volta che c'è un aggiornamento.
  • per l'eliminazione, il record non sarà disponibile, quindi non è possibile interrogare esso.

Ho pensato di utilizzare Timestamp per evitare i trigger, ma non è possibile convertire Timestamp in Datetime.

EDIT: O forse è possibile utilizzare un "metatabella" dove nei trigger potrete salvare la modifica Date

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 

spero che sia utile

+1

stai attento ai blocchi. Se si eseguono alcune transazioni contemporaneamente che modificano la stessa tabella (righe diverse che non causerebbero il blocco), dovranno attendere il proprio turno per aggiornare la riga della tabella del registro per quella tabella. –

+0

Si, hai ragione, la prego di modificare il codice in modo che rifletta i cambiamenti che hai citato? Io non sarà disturbato per quella –

1

senza trigger: si potrebbe avere un LastChgDate colonna sul tavolo e impostarla quando si inserisce/aggiorna/elimina una riga. Dovresti "cancella" dal usig una colonna di stato impostato su "D" o qualcosa di simile. Metti un indice su questa colonna e seleziona MAX() per vedere quando è stata apportata una modifica.

+0

Giusto per essere chiari, LastChgDate sarebbe un tipo datetime e si avrebbe bisogno di impostarlo su GetDate() su ogni INSERT/UPDATE. Inoltre, "DELETE" verrebbe gestito come AGGIORNATO con una modifica di stato a "D", e potrebbe quindi essere interrogato per l'ultima volta. –

+0

andare avanti e indietro tra una tabella di log e la colonna datetime nella tabella effettiva sembra ingombrante –

1

Beh, si potrebbe tenere una colonna con un "LASTUPDATEDATE" che è impostato per l'attuale server di data/ora su qualsiasi inserimento o aggiornamento. Quindi puoi semplicemente eseguire una query per la riga con il LastUpdateDate più recente.

5

Come mostrano le due risposte precedenti, in SQL Server non è disponibile alcuna funzionalità incorporata prontamente disponibile per le proprie esigenze.

Ci sono un sacco di viste gestionali dinamiche che possono indicarti alcuni dei tuoi punti di interesse, ad es. sys.dm_db_index_usage_stats che ti dice quando un determinato indice ha avuto il suo ultimo sollecitare o aggiornamento.

Ma non c'è davvero nulla nella scatola in sé che si possa sfruttare per ottenere tutte le informazioni che stai cercando - devi davvero farlo tu stesso, aggiungendo per es. campi datetime alle tue tabelle e riempiendoli di trigger.

Scusate, non posso darvi alcuna notizia migliore - è proprio così per ora.

In SQL Server 2008, si dispone di ulteriori nuove funzioni, che potrebbe coprire alcune delle vostre esigenze - check out:

Marc

2

su brevi periodi (dall'avvio del server) si controlla sys.dm_db_index_usage_stats last_user_update column. Ma dal momento che questo conta solo gli aggiornamenti dall'avvio del server, non può essere utilizzato per un lungo periodo di tempo.

Per lunghi periodi di tempo, se la tabella non è enorme, l'applicazione può memorizzare il tavolo CHECKSUM_AGG(ALL). Dovresti ricalcolarlo solo una volta all'avvio dell'applicazione e confrontarlo con il valore precedentemente memorizzato. Inoltre l'applicazione può rilevare le modifiche utilizzando il DMV. All'arresto dell'applicazione dovrebbe memorizzare il checksum della tabella corrente.

0

semplice! Innanzitutto aggiungi una colonna "LastUpdated". Assegnare il valore predefinito a GetDate(). Questo si prenderà cura di Insert Statements. In secondo luogo, aggiungere un trigger di aggiornamento che aggiorna LastUpdated a GetDate(). Gli aggiornamenti sono ora coperti. Infine aggiungi un campo bit/booleano IsDeleted con il valore predefinito di 0. Se un utente desidera eliminare una riga, capovolgi il bit. Dal momento che quando si "elimina" una fila, in realtà si sta aggiornando il campo IsDeleted (e quindi si utilizza un'azione Update), Elimina sono ora timestamp.

Per ottenere l'attività più recente sul tavolo: per ottenere solo il timestamp:

SELECT MAX(LastUpdated) FROM MyTable 

per avere maggiori informazioni:

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

Ovviamente se si aggiunge il campo di bit ISD, tutto il codice esistente dovrà essere ripetuto per garantire che i record cancellati non vengano utilizzati nel interrogazioni. – HLGEM

+0

Certo, non sarà indolore, ma mostrerà l'ultima attività sul tavolo, indipendentemente da cosa fosse. – Pulsehead

1

vorrei aggiungere rilevamento delle modifiche al mix - come opposto a Change Data Capture, non è una funzionalità solo Enterprise.

leggere su di esso in http://msdn.microsoft.com/en-us/library/cc280462.aspx

Simile al sys.dm_db_index_usage_stats, i dati non sono lì per sempre (anche se sopravvive riavvio del server ed è configurabile) e si dovrà estrarre e persistere il particolare pezzo di informazioni che sei cercando.

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() 
Problemi correlati