在ms sql中构建来自审计跟踪的快照表

时间:2016-08-22 20:47:33

标签: sql-server database

我遇到了与Building a snapshot table from audit records相关的问题。下面的代码部分地解决了我的问题

    Select * into #temp from (
SELECT Audit.PrimaryKeyValue as ID,Audit.FieldName,OldValue FROM audit left       JOIN (
SELECT Audit.FieldName,Audit.PrimaryKeyValue, MAX(UpdateDate) AS dateadded FROM audit GROUP BY FieldName,PrimaryKeyValue  
) maxtimestamp ON audit.FieldName = maxtimestamp.FieldName AND audit.updateDate = maxtimestamp.dateadded
where PrimaryKeyField='Id' and cast(UpdateDate as date)<=@Data) src
pivot(
max(src.OldValue)
for FieldName in (Centrala,ID_Grup,Pi, Ci, Pmt, Pneta, Rpp, Pd, UD, Suport1, Suport2, Suport3, Stare, 
Motiv, Observatii, Comentarii, Un, Data_ADD, Modified_Date, Scada, Fuel_base)
) piv;

如何在给定时刻根据审计跟踪表中的记录获取表的快照。 通过在临时表中复制实际表并根据审计内容更新它的值是一种解决方案吗? 我的英文程度不高! 感谢!!!

主表的结构是:

[ID] [int] IDENTITY(1,1) NOT NULL,
[Centrala] [int] NOT NULL,
[ID_grup] [nvarchar](50) NULL,
[Pi] [float] NULL,
[Ci] [float] NULL,
[Pmt] [float] NULL,
[Pneta] [float] NULL,
[Rpp] [float] NULL,
[Pd] [float] NULL,
[UD] [nvarchar](50) NULL,
[Suport1] [nvarchar](255) NULL,
[Suport2] [nvarchar](255) NULL,
[Suport3] [nvarchar](255) NULL,
[Stare] [int] NULL,
[Motiv] [nvarchar](max) NULL,
[Observatii] [nvarchar](max) NULL,
[Comentarii] [nvarchar](max) NULL,
[Un] [varchar](10) NULL,
[Data_ADD] [date] NULL,
[Modified_Date] [date] NULL,
[Scada] [nvarchar](100) NULL,
[Fuel_base] [nvarchar](255) NULL,

并且Audit表的结构是:

[AuditID] [int] IDENTITY(1,1) NOT NULL,
[Type] [char](1) NULL,
[TableName] [varchar](128) NULL,
[PrimaryKeyField] [varchar](1000) NULL,
[PrimaryKeyValue] [varchar](1000) NULL,
[FieldName] [varchar](128) NULL,
[OldValue] [varchar](1000) NULL,
[NewValue] [varchar](1000) NULL,
[UpdateDate] [datetime] NULL,
[UserName] [varchar](128) NULL

用户可以修改主表中的值,包括删除整行,审计表捕获所有修改。我必须在特定日期及时回溯主表的内容。我认为Audit表中的列名是富有表现力的,Type有三个值'U','I','D'用于更新,插入和删除操作。另一个问题是,如果Audit表包含主表中行的修改,并且快照的日期低于Audit中的updateDate,那么我必须选择OldValue else NewValue。它是正确的? 谢谢你@ Nick.McDermaid的回复!!

1 个答案:

答案 0 :(得分:0)

我发现了一个非常难看的解决方案,但我认为它现在可以正常工作

 Declare @data date     
 select @data='2016.02.2'
 select * into #Grup1 from Grupuri
 --Apply to actual values most oldest values from Audit
 select * into #temp from ( 
 SELECT
 Audit.PrimaryKeyValue as ID,Audit.FieldName,OldValue
 FROM audit inner JOIN (
 SELECT Audit.FieldName,Audit.PrimaryKeyValue, min(UpdateDate) AS dateadded               FROM audit GROUP BY FieldName,PrimaryKeyValue  
 ) maxtimestamp ON audit.FieldName = maxtimestamp.FieldName AND   audit.updateDate = maxtimestamp.dateadded
 where PrimaryKeyField='Id' and TableName='Grupuri' ) src 
 pivot(
 max(src.OldValue)
 for FieldName in (Centrala,ID_Grup,Pi, Ci, Pmt, Pneta, Rpp, Pd, UD, Suport1,    Suport2, Suport3, Stare, 
 Motiv, Observatii, Comentarii, Un, Data_ADD, Modified_Date, Scada,    Fuel_base)
 ) piv;

 UPDATE #Grup1 SET  Pi= (case When b.Pi is not null then b.Pi else #Grup1.Pi   end), 
               Ci=case When b.Ci is not null then b.Ci else #Grup1.Ci end, 
               Pmt=case When b.Pmt is not null then b.Pmt else #Grup1.Pmt end,
               Pneta=case When b.Pneta is not null then b.Pneta else #Grup1.Pneta end, 
               Rpp=case When b.Rpp is not null then b.Rpp else #Grup1.Rpp end, 
               Pd=case When b.Pd is not null then b.Pd else #Grup1.Pd end, 
               UD=case When b.Ud is not null then b.Ud else NULL end, 
               Suport1=case When b.Suport1 is not null then b.Suport1 else #Grup1.Suport1 end, 
               Suport2=case When b.Suport2 is not null then b.Suport2 else #Grup1.Suport2 end, 
               Suport3=case When b.Suport3 is not null then b.Suport3 else #Grup1.Suport3 end, 
               Stare=case When b.Stare is not null then b.Stare else #Grup1.Stare end, 
               Motiv=case When b.Motiv is not null then b.Motiv else #Grup1.Motiv end, 
               Observatii=case When b.Observatii is not null then b.Observatii else #Grup1.Observatii end, 
               Comentarii=case When b.Comentarii is not null then b.Comentarii else #Grup1.Comentarii end,
               Un=case When b.Un is not null then b.Un else #Grup1.Un end, 
               Scada= case When b.Scada is not null then b.Scada else #Grup1.Scada end, 
               Fuel_base=case When b.Fuel_base is not null then b.Fuel_base    else #Grup1.Fuel_base end  
 FROM   #temp b WHERE  #Grup1.id = b.id
 --Apply new values updated up to @data
 select * into #temp1 from ( 
 SELECT
 Audit.PrimaryKeyValue as ID,Audit.FieldName,NewValue
 FROM audit left JOIN (
 SELECT Audit.FieldName,Audit.PrimaryKeyValue, MAX(UpdateDate) AS dateadded   FROM audit GROUP BY FieldName,PrimaryKeyValue  
 ) maxtimestamp ON audit.FieldName = maxtimestamp.FieldName AND    audit.updateDate = maxtimestamp.dateadded
  where PrimaryKeyField='Id' and TableName='Grupuri' 
  and cast(UpdateDate as date) <=@Data) src 
  pivot(
  max(src.NewValue)
  for FieldName in (Centrala,ID_Grup,Pi, Ci, Pmt, Pneta, Rpp, Pd, UD,   Suport1, Suport2, Suport3, Stare, 
  Motiv, Observatii, Comentarii, Un, Data_ADD, Modified_Date, Scada,    Fuel_base)) piv;

 UPDATE #Grup1 SET  Pi= (case When b.Pi is not null then b.Pi else #Grup1.Pi   end), 
               Ci=case When b.Ci is not null then b.Ci else #Grup1.Ci end, 
               Pmt=case When b.Pmt is not null then b.Pmt else #Grup1.Pmt end,
               Pneta=case When b.Pneta is not null then b.Pneta else #Grup1.Pneta end, 
               Rpp=case When b.Rpp is not null then b.Rpp else #Grup1.Rpp end, 
               Pd=case When b.Pd is not null then b.Pd else #Grup1.Pd end, 
               UD=case When b.Ud is not null then b.Ud else '-' end, 
               Suport1=case When b.Suport1 is not null then b.Suport1 else #Grup1.Suport1 end, 
               Suport2=case When b.Suport2 is not null then b.Suport2 else #Grup1.Suport2 end, 
               Suport3=case When b.Suport3 is not null then b.Suport3 else #Grup1.Suport3 end, 
               Stare=case When b.Stare is not null then b.Stare else #Grup1.Stare end, 
               Motiv=case When b.Motiv is not null then b.Motiv else #Grup1.Motiv end, 
               Observatii=case When b.Observatii is not null then b.Observatii else #Grup1.Observatii end, 
               Comentarii=case When b.Comentarii is not null then b.Comentarii else #Grup1.Comentarii end,
               Un=case When b.Un is not null then b.Un else #Grup1.Un end, 
               Scada= case When b.Scada is not null then b.Scada else #Grup1.Scada end, 
               Fuel_base=case When b.Fuel_base is not null then b.Fuel_base   else #Grup1.Fuel_base end  
   FROM   #temp1 b
   WHERE  #Grup1.id = b.id

   Delete from #Grup1 where Data_ADD>@data 

   Select * from #Grup1
   union
   Select Old_ID,Centrala,ID_Grup,Pi, Ci, Pmt, Pneta, Rpp, Pd, UD,    Suport1,Suport2, Suport3, Stare, Motiv, 
   Observatii, Comentarii, Un, Data_ADD, Modified_Date, Scada, Fuel_base From     DeletedGrupuri where Deleted<=@Data and Old_ID is not null order by ID
  drop table #temp
  drop table #temp1
  drop table #Grup1

如果有人有更好的解决方案或者可以改进此代码,请帮助我。此外,我还可以修改表Audit的设计以简化此过程。 谢谢!