存储多个SQL行数据版本的建议技术

时间:2011-12-16 02:14:40

标签: sql

我正在开发一个应用程序,它需要存储以前版本的数据库表行以维护更改历史记录。我正在同一个表中记录历史记录,但需要通过唯一标识符访问最新数据,该标识符不会随新版本而更改。关于如何做到这一点,我有一些想法,只是想找到关于这样做的最佳方式的一些想法,或者是否有任何理由不使用我的一个想法:

  1. 为每个行版本创建一个新行,并使用一个字段指示哪一行是当前行。这样做的缺点是新版本具有不同的主键,对旧版本的任何引用都不会返回当前版本。

  2. 更新数据时,旧行版本将复制到新行,新版本将替换旧行。当前行可以通过相同的主键访问。

  3. 添加仅包含主键的第二个表,将列添加到另一个表中,该表是新表主键的外键。使用与选项1中描述的方法相同的方法来存储多个版本,并创建一个使用新表的主键查找当前版本的视图。

5 个答案:

答案 0 :(得分:2)

PeopleSoft使用(使用?)“有效日期记录”。花了一点时间来掌握它,但它达到了它的目的。业务键始终由EFFDT列(生效日期)扩展。因此,如果您有一个表EMPLOYEE [EMPLOYEE_ID,SALARY],它将成为EMPLOYEE [EMPLOYEE_ID,EFFDT,SALARY]。

检索员工的薪水:

SELECT e.salary
  FROM employee e
  WHERE employee_id = :x
    AND effdt = (SELECT MAX(effdt)
                   FROM employee
                   WHERE employee_id = :x
                     AND effdt <= SYSDATE)

一个有趣的应用是未来的约会记录:你可以让每位员工在明年1月1日起增加10%,并提前几个月预先填好桌子。当SYSDATE越过1月1日时,新薪水将生效。此外,它有利于运行历史报告。您可以插入过去的日期,而不是使用SYSDATE,以查看过去那段时间运行时报告的工资(或汇率等)。

在这种情况下,记录永远不会更新或删除,您只需添加具有新生效日期的记录。进行更详细的查询,但它起作用并开始成为(我敢说)正常。有很多页面,例如:http://peoplesoft.wikidot.com/effective-dates-sequence-status

答案 1 :(得分:1)

#3可能是最好的,但是如果你想将数据保存在一个表中,我想你可以添加一个datetime列,其中每个新行都填充了now()值,然后你至少可以按日期排序desc limit 1。

总的来说 - 多个版本需要更多关于你想要有效做什么的信息,就像编程一样...即需要更多关于你想做什么的信息。

[R

答案 2 :(得分:0)

您是否考虑过使用AutoAudit

  

AutoAudit是一个SQL Server(2005,2008)创建的Code-Gen实用程序   审计跟踪触发器:

     
      
  • Created,CreatedBy,Modified,ModifiedBy和RowVersion(递增INT)列到表
  •   
  • 将事件记录到审核表
  •   
  • 更新记录到审核表的新旧值
  •   
  • 删除将所有最终值记录到Audit tbale
  •   
  • 查看重建已删除的行
  •   
  • UDF重建行历史
  •   
  • 用于跟踪架构更改的架构审核触发器
  •   
  • 当Alter Table更改表格时重新编码gens触发
  •   

答案 3 :(得分:0)

对我来说,历史表总是分开的。所以,我肯定会这样做,但为什么要创建一些复杂的版本控制的东西,你需要查看当前的生产记录。在报告中,这会导致非常不必要的讨厌的工会。

有一个主键,谁在乎其他什么 TableHist 包含以下列:递增int / bigint主键,历史记录写入日期/时间,写入的历史记录,记录类型(I,U,D表示插入,更新,删除),表格中的PK为TableHist上的FK,其余列的所有其他列具有相同的名称都在TableHist表中。

如果您创建此历史表结构并通过上的触发器填充它,您将拥有所关注表中每行的所有版本,并且可以轻松确定原始记录,每次更改,和删除记录。如果您要报告,您只需使用历史表来获取您想要的所有信息。

答案 4 :(得分:0)

create table table1 (
    Id int identity(1,1) primary key,
    [Key] varchar(max),
    Data varchar(max)
)
go

create view view1 as
with q as (
    select [Key], Data, row_number() over (partition by [Key] order by Id desc) as 'r'
    from table1
)
select [Key], Data from q where r=1
go

create trigger trigger1 on view1 instead of update, insert as begin
    insert into table1 
    select [Key], Data 
    from (select distinct [Key], Data from inserted) a
end
go

insert into view1 values
     ('key1', 'foo')
    ,('key1', 'bar')

select * from view1

update view1
set Data='updated'
where [Key]='key1'

select * from view1

select * from table1

drop trigger trigger1
drop table table1
drop view view1

结果:

Key Data
key1    foo

Key Data
key1    updated

Id  Key Data
1   key1    bar
2   key1    foo
3   key1    updated

我不确定是否需要使用。