在DBMS中处理完整历史记录的最佳设计

时间:2017-10-14 21:51:05

标签: sql database-design

我正在开发一个带有多个实体和关系的DBMS的网站。我希望网站的用户能够查看某些内容中已更改内容的完整历史记录,例如何时,由谁和一个领域被改变为什么。

到目前为止,我已经考虑使用链接列表方法,您只需坚持而不是更新实体,并将ID保存到上一个实体。但是,由于关系可以改变,我不知道链接实体在上次更新时是如何实现的。 我的意思是关系可以改变:说我有一个Person实体,它与另一个Person实体有连接。如果我只保留另一个人的ID,我不知道其他人员字段是否已更新,例如如果另一个人例如更改了其名称字段。请参阅下文以进一步了解情况。

另一个方法可能是按顺序保存对数据库的每个更改,并简单地恢复到给定的更改,例如保存每个sql查询。

有谁知道处理这个问题的正确方法?提前致谢。

更新

假设我有一个名为Person的实体(见下文)。这个人可以有很多父母和孩子。让我们说用户可以更新现有Person中的值。每当用户例如更新名称字段时,我想保存此更改,以便其他用户可以根据需要还原更改。如上所述,如果我只保留父母的身份证,我就不知道具有该身份证的人是否已经改变。例如,如果父母姓名已更新。

Person {
    int id;
    String name; 
    List<Person> parents;
    List<Person> children;
}

总之:我需要在更新时显示此Person实体的列表。在此列表中,我需要查看Persons字段确实包含的内容,以及其父母和孩子如何查看给定更改的时间。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,那么每当对表进行更改并允许检索所做的更改时,您是想创建某种审计历史记录吗?

  

每当用户例如更新名称字段时,我想保存此更改,以便其他用户可以根据需要还原更改

考虑你的实体Person,它有一个数据库表,如:

Person
id INT
name NVARCHAR(20)
parentId INT

要保留更改历史记录,您可以在数据库中拥有“人员更改历史记录”表:

PersonCH
RevisionCount INT
id INT
name NVARCHAR 
parentId INT
ChangeDateTime DATETIME
ChangedByUserID INT

为了解释这是如何工作的,让我们来看看你的例子:

让我们添加一个叫John的人:

INSERT INTO Person VALUES (100,'John',99);

同时,我们还应该在历史记录表中添加记录:

INSERT INTO PersonCH (1,100,'John',99,GETDATE(),123);

如果我们改变John的名字,我们再次在历史表中添加一条新记录:

UPDATE Person SET name = 'Jim' WHERE id = 100;
INSERT INTO PersonCH (2,100,'Jim',99,GETDATE(),123);

实际上,上面的INSERT语句将位于AFTER INSERT和/或AFTER UPDATE触发器中,因此我们无需依赖于始终在我们的应用程序中指定它。

因此,我们的历史记录表现在具有此人员更改的审计跟踪,我们可以使用

查看
SELECT * FROM PersonCH WHERE id = 100 ORDER BY RevisionCount DESC;