Sql server 比较审核日志表中更新列的最新记录和以前记录

Sql server 比较审核日志表中更新列的最新记录和以前记录,sql-server,pivot,unpivot,Sql Server,Pivot,Unpivot,我面临的场景是,我需要从审计日志表中获取数据,并显示新旧值 例如,下面是个人的audit\u Log表格 AUDIT_ID PERSON_ID OPERATION NAME ADDRESS AGE DOY 1 101 I Prashant Andheri 21 1991 2 101

我面临的场景是,我需要从审计日志表中获取数据,并显示新旧值

例如,下面是个人的
audit\u Log
表格

AUDIT_ID       PERSON_ID       OPERATION       NAME       ADDRESS       AGE     DOY 
    1           101             I           Prashant        Andheri     21      1991 
    2           101             U           Prashant1       Santacruz   22      1990 
    3           101             U           rashant2        Parle       23      1989
我想要所有列的最新值和以前的值,如下所示,

PERSON_ID       COLUMNS      OLD_VALUE       NEW_VALUE 
101             OPERATION       U               U 
101             NAME            PRASHANT1       PRASHANT2 
101             ADDRESS         Santacruz       Parle 
101             AGE             22              23 
101             BIRTH_YEAR      1990            1989 
谁能帮我从上表中得到这个结果

谢谢,
Prashant

我试图找到一个函数/查询来执行您想要的操作,但什么也没找到。所以我制定了一个程序来验证是否有效

CREATE PROCEDURE _spManageAuditLog 
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT AUDIT_ID, PERSON_ID, OPERATION, NAME, [ADDRESS], AGE, DOY, count(1)
    FROM dbo.audit_Log  
    GROUP BY AUDIT_ID, PERSON_ID, OPERATION, NAME, [ADDRESS], AGE, DOY;


CREATE TABLE #row (personId Int, operation char(1), name nvarchar(250),[address] nvarchar(250), age smallint,
doy smallint);


CREATE TABLE #out (PersonID Int, [columnName] nvarchar(250), OLD_VALUE nvarchar(250),NEW_VALUE  nvarchar(250));

--cursor variable
DECLARE
@AUDIT_ID   int,
@PERSON_ID  int,
@OPERATION  char,
@NAME   nvarchar,
@ADDRESS    nvarchar,
@AGE    smallint,
@DOY    smallint;


DECLARE myCursor CURSOR FOR 
    SELECT AUDIT_ID, PERSON_ID, OPERATION, NAME, [ADDRESS], AGE, DOY
    FROM dbo.audit_Log  

OPEN myCursor
FETCH NEXT FROM myCursor INTO @AUDIT_ID, @PERSON_ID, @OPERATION, @NAME, @ADDRESS, @AGE, @DOY

WHILE @@FETCH_STATUS = 0
BEGIN
    declare @countTempData int;
    select @countTempData= count(1) from #row;

    IF @countTempData=0 
     BEGIN
        Insert into #row VALUES(@PERSON_ID, @OPERATION, @NAME, @ADDRESS, @AGE, @DOY);
        --to debug
        --SELECT * FROM #row;
     END 
    ELSE
     BEGIN
        --do comparison previus row


        INSERT INTO #out VALUES (@PERSON_ID, 'Operation', (SELECT TOP(1) OPERATION FROM #row) , @OPERATION );
        INSERT INTO #out VALUES (@PERSON_ID, 'Name',(SELECT TOP(1) NAME FROM #row), @NAME );
        INSERT INTO #out VALUES (@PERSON_ID, 'Address',(SELECT TOP(1) ADDRESS FROM #row), @ADDRESS );
        INSERT INTO #out VALUES (@PERSON_ID, 'Age',(SELECT TOP(1) AGE FROM #row), @AGE );
        INSERT INTO #out VALUES (@PERSON_ID, 'BirthYear',(SELECT TOP(1) DOY FROM #row), @DOY );


        --new item became temp item
        TRUNCATE TABLE #row
        INSERT INTO #row VALUES(@PERSON_ID, @OPERATION, @NAME, @ADDRESS, @AGE, @DOY);
        --to debug
        --SELECT * FROM #row;

     END

    -- Get the next.
    FETCH NEXT FROM myCursor INTO @AUDIT_ID, @PERSON_ID, @OPERATION, @NAME, @ADDRESS, @AGE, @DOY
END 
CLOSE myCursor;
DEALLOCATE myCursor;

SELECT * FROM #out;


END
GO  
注:

  • 您需要将所有审核列值转换为通用类型。我 选择了
    VARCHAR(100)
    ,但您可能需要选择其他内容
  • 当仅存在一条审核记录时,此代码也起作用。在这种情况下 对于
    旧值
参考资料:


编辑:排除查询末尾的错误代码

请将表结构像表一样发布,而不是像内联字符串一样发布,然后发布结果表?thkHi,我已经更新了表结构,请检查。嗨,Alex,谢谢你的回复,但是查询不工作,并且给出了语法错误。我不明白该方法。@user1150365我已删除了最后两行复制/粘贴错误的内容
SELECT PERSON_ID, [COLUMNS], OLD_VALUE, NEW_VALUE
FROM(
    SELECT TOP 2 PERSON_ID, ( CASE ( ROW_NUMBER() OVER( ORDER BY AUDIT_ID DESC )) WHEN 1 THEN 'NEW_VALUE' ELSE 'OLD_VALUE' END ) AS [Version],
        CAST( OPERATION AS VARCHAR( 100 )) AS OPERATION, CAST( NAME AS VARCHAR( 100 )) AS NAME,
        CAST( ADDRESS AS VARCHAR( 100 )) AS ADDRESS, CAST( AGE AS VARCHAR( 100 )) AS AGE, CAST( DOY AS VARCHAR( 100 )) AS DOY
    FROM audit_Log
    WHERE PERSON_ID = 101
    ORDER BY AUDIT_ID DESC ) AS SourceData
UNPIVOT(
    COL_VALUE FOR [COLUMNS] IN( NAME, ADDRESS, OPERATION, AGE, DOY )
    ) AS UnpivotColumns
PIVOT(
    MIN( COL_VALUE ) FOR [Version] IN( [NEW_VALUE], [OLD_VALUE] )
    ) AS PivotOldNew