Sql server 从审核表中查找更改

Sql server 从审核表中查找更改,sql-server,tsql,audit,Sql Server,Tsql,Audit,我有如下审计表中的数据 我需要从此表中获取更新的列和数据详细信息 预期结果是: 员工姓名:从Jone到Jhone 员工年龄:25至20岁 员工姓名:从约翰尼到琼斯,员工年龄:18岁至25岁 我怎样才能做到这一点 更新 当一条记录被更新时,我将在审计表中插入两行。第一条记录为Old(auditDataState),更新前有数据,第二条记录为New(auditDataState),更新后有数据 因此,每次更新在审计表中都有两条记录,分别为Old和New,其中包含新旧值 我需要根据审核表中的upda

我有如下审计表中的数据

我需要从此表中获取更新的列和数据详细信息

预期结果是:

员工姓名:从Jone到Jhone

员工年龄:25至20岁

员工姓名:从约翰尼到琼斯,员工年龄:18岁至25岁

我怎样才能做到这一点

更新

当一条记录被更新时,我将在审计表中插入两行。第一条记录为
Old(auditDataState)
,更新前有数据,第二条记录为
New(auditDataState)
,更新后有数据

因此,每次更新在审计表中都有两条记录,分别为OldNew,其中包含新旧值

我需要根据审核表中的
updateColumns
从审核表中获取更新的数据。(我正在将更新的列存储在updateColumns列中)


我不需要第一行是
员工姓名:从Jone到Jhone
。只需识别更新的值。

这将提供您问题中指定的结果,尽管它远不是一个合理或可扩展的解决方案。如果可能的话,我建议您完全重新进行变更审核:

declare @EmpAudit table (
      empID int
    , empName varchar(50)
    , empAge int
    , auditDataState varchar(50)
    , auditDMLAction varchar(50)
    , auditUser varchar(50)
    , auditDateTime datetime
    , updateColumns varchar(50)
);

insert into @EmpAudit values
      (1, 'Alex', 22, 'New', 'Insert','c@a.com',getdate(),''),
      (2, 'Jhonny', 18, 'New', 'Insert','c@a.com',getdate()-0.5,''),

      (2, 'Jhonny', 18, 'Old', 'Update','b@a.com',getdate()-1,'Employee Name, Employee Age'),
      (2, 'Jone', 25, 'New', 'Update','b@a.com',getdate()-1.5,'Employee Name, Employee Age'),

      (2, 'Jone', 25, 'Old', 'Update','a@a.com',getdate()-2,'Employee Age'),
      (2, 'Jone', 30, 'New', 'Update','a@a.com',getdate()-2.5,'Employee Age'),

      (2, 'Jone', 30, 'Old', 'Update','a@a.com',getdate()-3,'Employee Age'),
      (2, 'Jone', 20, 'New', 'Update','a@a.com',getdate()-3.5,'Employee Age'),

      (2, 'Jone', 20, 'Old', 'Update','a@a.com',getdate()-4,'Employee Name'),
      (2, 'Jhone', 20, 'New', 'Update','a@a.com',getdate()-4.5,'Employee Name');

with d as
(
    select empID
            ,empName
            ,empAge
            ,auditDataState
            ,auditDMLAction
            ,auditUser
            ,auditDateTime
            ,updateColumns
            ,row_number() over (partition by empID order by auditDateTime) as rn
    from @EmpAudit
)
select case when o.empName <> n.empName then 'Employee Name : from ' + o.empName + ' to ' + n.empName else '' end
      +case when charindex(',',o.UpdateColumns) > 0 then ', ' else '' end
      +case when o.empAge <> n.empAge then 'Employee Age : from ' + cast(o.empAge as varchar(3)) + ' to ' + cast(n.empAge as varchar(3)) else '' end as Change
from d as o
    join d as n
        on o.empID = n.empID
            and o.updateColumns = n.updateColumns
            and o.rn = n.rn+1
            and n.auditDataState = 'New'
where o.auditDataState = 'Old';

您是否希望SQL中第一列的第一行值为
“员工姓名:从Jone到Jhone”
?这可不容易。特别是当您稍后混合数据类型时(我假设
empAge
int
)。您最好提供一个同时具有值(旧值和新值)的数据集,并使用您的应用程序执行显示格式。在您的DBMS中,这是一项非常糟糕的任务。@Larnu感谢您的回复。请检查更新的问题。我不需要第一行是
员工姓名:从Jone到Jhone
。只需要识别更新的值。然后我可以做显示格式。你不用说你用的是哪个版本。从2016年起,时态表非常适合您的需求。查看您提供的数据,所有更改都同时发生。我们如何确定哪一个“新”行与哪一个“旧”行相关?此外,此解决方案需要具有多大的通用性?由于您的
updateColumns
值与正在更新的实际列名不对应,因此需要手动映射,或者需要检查每个潜在的数据列。谢谢您的回答。这就是我一直在寻找的答案。顺便说一句,像这样的情况是有问题的@Bishan不用担心:)如果这是您需要的答案,请将其标记为这样,以方便其他堆栈溢出用户。是的。这就是我一直在寻找的答案。顺便说一句,在本例中这样的情况下仍然无法返回正确的数据@Bishan当然有一个问题,您在变更审核过程中没有提供足够的信息来指定变更的顺序。这就是我建议您重新审视整个流程的原因。它是旧的=
30
,新的=
20
Change
-----------------------------------------------------------------
Employee Name : from Jone to Jhone
Employee Age : from 30 to 20
Employee Age : from 25 to 30
Employee Name : from Jhonny to Jone, Employee Age : from 18 to 25