0

我必须从 SQL Server 2016 时态表中构建历史数据。

考虑以下表结构:

  • 表名:对象
  • 列:ObjectId(主键)、名称(Varchar 100)、价格(int)、UpdatedBy(varchar 100)、UpdatedOn(日期时间)、ValidFrom(生成的日期时间)、ValidTo(生成的日期时间)

Objects_History该表在时态表中也有记录

现在,要求是我们可以通过以下方式显示任何特定对象的审计跟踪:

FieldName  |   OldValue  |  NewValue  |  UpdatedBy
-----------+-------------+------------+-----------
Name       |  Obj_Name2  | Obj_Name3  | Owner2      
Name       |  Obj_Name1  | Obj_name2  | Owner1      
Price      |   100       | 200        | Owner1       
Name       |  Obj_Name0  | Ojb_Name1  | Owner0      

最新记录应该放在第一位。

4

1 回答 1

0

我花了一些时间,但我通过一些研发解决了这个问题。以下查询将解释解决方案。它创建一个表“项目”,插入一些记录,然后更新一些记录。之后,它会获取任何给定记录的审计跟踪信息。

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 
于 2018-07-09T15:52:16.737 回答