我花了一些时间,但我通过一些研发解决了这个问题。以下查询将解释解决方案。它创建一个表“项目”,插入一些记录,然后更新一些记录。之后,它会获取任何给定记录的审计跟踪信息。
CREATE TABLE [dbo].[Item](
ItemID [int] Identity ,
[Name] [varchar](100) NOT NULL,
Price int NOT NULL,
UpdatedBy varchar(100) NOT NULL,
UpdatedOn Datetime NOT NULL,
[ValidFrom] [datetime2](2) GENERATED ALWAYS AS ROW START NOT NULL,
[ValidTo] [datetime2](2) GENERATED ALWAYS AS ROW END NOT NULL,
PRIMARY KEY CLUSTERED
(
ItemID ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo])
) ON [PRIMARY]
WITH
(
SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[Item_History] )
)
GO
-- Insert Some test Data
Insert Into Item ([Name], Price, UpdatedBy, UpdatedOn) Values ('Item 1' , 100, 'user 1', GETDATE())
Insert Into Item ([Name], Price, UpdatedBy, UpdatedOn) Values ('Item 2' , 100, 'user 1', GETDATE())
Insert Into Item ([Name], Price, UpdatedBy, UpdatedOn) Values ('Item 3' , 100, 'user 2', GETDATE())
Insert Into Item ([Name], Price, UpdatedBy, UpdatedOn) Values ('Item 4' , 100, 'user 2', GETDATE())
-- Update some records
Update Item
Set Price = 200 , UpdatedBy = 'user 3', UpdatedOn=GETDATE() where [Name] = 'Item 2'
Update Item
Set Price = 200 , UpdatedBy = 'user 4', UpdatedOn=GETDATE() where [Name] = 'Item 4'
-- Build Audit trail informaiton
DECLARE @tempTable TABLE ( ColName varchar(100), ColValue varchar(max), ValidFrom Datetime, ValidTo DateTime, UpdatedBy varchar (100), UpdatedOn Datetime);
DECLARE @tempTable2 TABLE (Id int identity(1,1) primary key clustered, ColName varchar(100), ColValue varchar(max), ValidFrom Datetime, ValidTo DateTime, UpdatedBy varchar (100), UpdatedOn DateTime);
WITH T1 AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ItemID, colname ORDER BY ValidFrom)
- ROW_NUMBER() OVER (PARTITION BY ItemID, colname, Colvalue ORDER BY ValidFrom) AS Grp,
IIF(DENSE_RANK() OVER (PARTITION BY ItemID, colname ORDER BY Colvalue) +
DENSE_RANK() OVER (PARTITION BY ItemID, colname ORDER BY Colvalue DESC) = 2, 0,1) AS HasChanges
FROM
(SELECT * FROM Item For SYSTEM_TIME ALL Where [Name] = 'Item 4' ) AS Records
CROSS APPLY ( VALUES
('Name', CAST([Name] AS VARCHAR(100))),
('Price', CAST(Price AS VARCHAR(50))),
('UpdatedBy' , CAST(UpdatedBy AS VARCHAR(100))),
('UpdatedOn' , CAST(UpdatedOn AS VARCHAR(100)))
) CA(Colname, Colvalue)
)
INSERT @tempTable ( Colname, Colvalue, ValidFrom, ValidTo, UpdatedBy, UpdatedOn)
SELECT
colname, Colvalue, MIN(ValidFrom) AS ValidFrom, MAX(ValidTo) AS ValidTo, UpdatedBy, UpdatedOn
FROM T1 WHERE HasChanges = 1
GROUP BY colname, Colvalue, UpdatedBy, UpdatedOn, Grp
INSERT @tempTable2 ( Colname, Colvalue, ValidFrom, ValidTo, UpdatedBy, UpdatedOn)
SELECT
Colname, Colvalue, ValidFrom, ValidTo , UpdatedBy , UpdatedOn
FROM @tempTable
order by colName, validto Asc
Select
ColName As FieldName,
ColValue as OldValue,
Case
When
ValidTo = '9999-12-31 23:59:59.990'
THEN
NULL
ELSE
Lead(ColValue, 1, colValue) Over (Order By colName)
END As NewValue,
Lead(UpdatedBy, 1, UpdatedBy) Over (Order By colName) As UpdatedBy,
UpdatedOn,
Case
When
ValidTo = '9999-12-31 23:59:59.990'
THEN
CAST (1 as bit)
ELSE
CAST (0 as bit)
END As IsCurrentValue
from @tempTable2