简体   繁体   中英

SQL Server row date last modified

A colleague of mine says that SQL Server saves the date and time of last modification in a "hidden column" in each record. I am pretty sure that he said something wrong. Can you confirm this to me?

As the others are hinting at, your colleague must be talking gibberish, or referring to something else. The on-disk structure for a record, or page for that sake, does not contain any references to the time of the last update. While you can find info regarding the last update at the object level, no such info is available at the record/row level.

There is no hidden column, maintained on a per-row basis, that contains the date/time of the last modification. Nor is there a column containing the identity of the user who performed such a change, nor is there a column that identifies what the last change performed was (insert or update).

If you want any of these features, you have to implement them. For some users, every last bit of overhead could matter to them, so having hidden features (with hidden costs) would not be acceptable.

From Pinal Dave , there is a DMV that you can use to get this information. Your colleague might be referring to the TIMESTAMP for a modified row, but as far as I know it only maintains that if you ask it to by explicitly adding a column of that type.

SELECT OBJECT_NAME(OBJECT_ID) AS DatabaseName, last_user_update,*
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID( 'AdventureWorks')
AND OBJECT_ID=OBJECT_ID('test');

If you want to know when a specific row was last updated, you should maintain a "LastUpdated" timestamp column in the table and update that upon every UPDATE (eg automatically via trigger)

You can try to read SQL Server transaction log using PageID.

It's not a guaranteed way, but it works in many cases, and a little more accurate than querying index statistics

/* This is example how to query datetime of data changes using SQL Server 
   transaction log, if audit routine wasn't set */

USE [AdventureWorksDW2017]
GO

UPDATE dbo.FactFinance
SET Date = GETDATE(), Amount = Amount + 1
WHERE FinanceKey = 1
GO

WITH main AS
(   
    SELECT 
        replace(replace(sys.fn_PhysLocFormatter (%%physloc%%), ')', ''), '(', '') page,
        FinanceKey, Date, Amount
    FROM 
        dbo.FactFinance (NOLOCK)   
    WHERE 
        FinanceKey = 1
),
tlog AS
( 
    SELECT 
        page, l2.[Begin Time], L2.[End Time],
        l1.AllocUnitName l1_uname, l2.[Transaction Name] l2_tname,
        l1.[Transaction ID]
    FROM 
        main
    JOIN
        sys.fn_dblog(NULL, NULL) l1 ON PATINDEX('%'+main.page+'%', l1.[Lock Information]) > 0
    LEFT JOIN 
        sys.fn_dblog(NULL, NULL) l2 ON l2.[Transaction ID] = l1.[Transaction ID]  
)
SELECT 
    PAGE, [Transaction ID], 
    MIN([Begin Time]), MIN([End Time]),
    MIN(l1_uname), MIN(l2_tname)
FROM
    tlog
GROUP BY 
    [Transaction ID], page

I know this is old, but one easy way to achieve this would be to enable table versioning (system-versioned temporal tables). This way you can use the SysStartTime as your LastModified column.

When was a record last updated, and who updated it can be maintained by adding a last_updated column with a default value of GetDate(). The last update user name is tricky since your app is most likely using a common database connection. The user name can be filled by adding it as a customization to all insert and update procedures and passing the AD, SSO, or login credentials -- whatever makes sense for your authentication method.

The last update column is so helpful and necessary that it should be included as a set option for the database or at least the table. Why? Try getting this information without it, after the fact has been entered (hint, if you have an identity field -- it "may" help, but could be unreliable).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM