数据库 – 数据版本

关于在数据库中对数据进行版本控制,我已经阅读了几个关于SO的问题(比如这个 )。

我喜欢提到的一些build议。 我有最长的时间想(需要)修改我的许多表,但从来没有解决它。 作为一名程序员,只有简单的数据库工作,我想知道如何去做这件事。

我没有要求SQL语法中的实际解决scheme。 我终究可以为自己弄清楚(或者在时间到了的时候贴出来)。 我只是要求人们评论他们如何去做,如果我要修改数以亿计的logging,那么可能会出现任何潜在的性能问题。 或者任何其他的build议,只要它是基于下面的例子。

给一个简单的例子:

Person ------------------------------------------------ ID UINT NOT NULL, PersonID UINT NOT NULL, Name VARCHAR(200) NOT NULL, DOB DATE NOT NULL, Email VARCHAR(100) NOT NULL Audit ------------------------------------------------ ID UINT NOT NULL, UserID UINT NOT NULL, -- Who TableName VARCHAR(50) NOT NULL, -- What OldRecID UINT NOT NULL, -- Where NewRecID UINT NOT NULL, AffectedOn DATE NOT NULL, -- When Comment VARCHAR(500) NOT NULL -- Why 

我不知道如何将审计表连接到任何其他表(如Person),如果TableName是一个string?

另外,假设我有三个GUI来填充:

  1. 一个特定的人员ID的完整logging
  2. 列出所有人的表视图(按ID)
  3. 显示每个人在每个条目(每人修订版本号,修订date,修订注释等)下面的每个人的视图,由最近的修订版本sorting。

要完成1和2,最好是查询Person表还是Audit表?

为了完成3,所谓的数据库专家是否会简单地获取所有logging并将其传递给软件进行处理,或者通过PersonID和Affected date进行分组? 这通常是在一个或多个查询处理?

多年来我做了各种各样的审计计划,现在我要实现这样的事情:

 Person ------------------------------------------------ ID UINT NOT NULL, PersonID UINT NOT NULL, Name VARCHAR(200) NOT NULL, DOB DATE NOT NULL, Email VARCHAR(100) NOT NULL Person_History ------------------------------------------------ ID UINT NOT NULL, PersonID UINT NOT NULL, Name VARCHAR(200) NOT NULL, DOB DATE NOT NULL, Email VARCHAR(100) NOT NULL AuditID UINT NOT NULL Audit ------------------------------------------------ ID UINT NOT NULL, UserID UINT NOT NULL, -- Who AffectedOn DATE NOT NULL, -- When Comment VARCHAR(500) NOT NULL -- Why 

当前logging总是在Person表中。 如果有更改,则创build审计logging,并将旧logging复制到Person_History表中(请注意,ID不会更改,并且可能有多个版本)

审计ID位于* _History表中,因此如果愿意,可以将多个logging更改链接到一个审计logging。

编辑:
如果对于每个基表没有单独的历史logging表,并且希望使用同一个表来保存旧的和“已删除”的logging,则必须用状态标志标记logging。 问题是,查询当前logging是一个真正的痛苦 – 相信我,我已经做到了。

你如何创build正常的表,每个logging(和ModifiedBy,如果你喜欢)有一个ModifiedDate列,并做所有的数据访问通过一个物化视图按ID组织数据,然后做一个HAVING ModifiedDate = MAX(ModifiedDate )?

这样,使用相同的ID添加新logging将从视图中删除旧logging。 如果您想查询历史logging,请不要浏览该视图

我总是发现用相同的列维护不同的表格会很复杂并且容易出错。

在DJ使用每个基表的历史表和Karl关于可能的性能问题的评论之后,为了找出将logging从一个表转移到另一个表的最快方法,我做了一些SQL研究。

我只是想logging我发现的:

我想我将不得不做一个SQL提取从基表加载logging,然后SQL推送将logging放入历史表,然后更新基表插入更改的数据。 共有3笔交易。

但令我惊讶的是,我意识到可以使用SELECT INTO语法使用一条SQL语句来完成前两个事务。 我敢打赌,这样做的performance会快一百倍。

那么这将使我们简单地用基表内的新数据更新logging。

我还没有find一个SQL语句一次做所有3个交易(我怀疑我会)。

我喜欢你的审计表,这是一个好的开始。 你的审计表有一个基数问题,所以我会把它作为两个表来处理:

 Person ------------------------------------------------ ID UINT NOT NULL, PersonID UINT NOT NULL, Name VARCHAR(200) NOT NULL, DOB DATE NOT NULL, Email VARCHAR(100) NOT NULL, AuditID UINT NOT NULL Audit ------------------------------------------------ ID UINT NOT NULL, TableName VARCHAR(50) NOT NULL, -- What TableKey UINT NOT NULL, CreateDate DATETIME NOT NULL DEFAULT(NOW), CreateUserID UINT NOT NULL, ChangeDate DATETIME NOT NULL DEFAULT(NOW), ChangeUserID UINT NOT NULL Audit_Item ------------------------------------------------ ID UINT NOT NULL, AuditID UINT NOT NULL, -- Which audit record UserID UINT NOT NULL, -- Who OldRecID UINT NOT NULL, -- Where NewRecID UINT NOT NULL, AffectedOn DATE NOT NULL, -- When Comment VARCHAR(500) NOT NULL -- Why 

build议的初始布局有一个单一的审计logging,指向(我假设)两个人的logging。 这个devise的挑战是:

  • 您的人员表中的哪些logging是当前的“真实”logging?
  • 您如何表示对“人员”logging进行更改的整个历史logging? 如果您指向Person表中的两条logging,请参阅第1点:哪一条logging是当前logging?
  • Create *,Change *字段从Audit_Itemlogging的集合中汇总。 他们只是为了方便访问。
  • Person表中的AuditID键允许您指向审计表并获取单个Person的历史logging,而无需使用WHERE TableName='Person'子句查询Audit表WHERE TableName='Person'