我正在开发一个应用程序,它需要存储以前版本的数据库表行以维护更改历史记录。我正在同一个表中记录历史记录,但需要通过唯一标识符访问最新数据,该标识符不会随新版本而更改。关于如何做到这一点,我有一些想法,只是想找到关于这样做的最佳方式的一些想法,或者是否有任何理由不使用我的一个想法:
为每个行版本创建一个新行,并使用一个字段指示哪一行是当前行。这样做的缺点是新版本具有不同的主键,对旧版本的任何引用都不会返回当前版本。
更新数据时,旧行版本将复制到新行,新版本将替换旧行。当前行可以通过相同的主键访问。
添加仅包含主键的第二个表,将列添加到另一个表中,该表是新表主键的外键。使用与选项1中描述的方法相同的方法来存储多个版本,并创建一个使用新表的主键查找当前版本的视图。
答案 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
我不确定是否需要使用。