具有数据库条目更改历史记录的方式


21

允许对数据库条目(数据)进行版本控制的方法有哪些?

考虑一下内容管理系统还原文章更改的能力。

他们的优点/缺点是什么?


1
您到底要版本什么?模式还是数据?
tdammers

1
我想对数据进行版本控制。留在CMS的例子,可以说的版本的文章
matcauthon 2012年

您可能需要研究Datomic。
dan_waterworth 2012年

Answers:


19

基本上有两种方法:审核表,其中存储了所有以前的值,或者在表中包括开始/结束日期,所有更新都创建了新记录,同时关闭了旧记录。

更新:SQL SERVER 2016支持将此作为设计模式/表类型— https://docs.microsoft.com/zh-cn/sql/relational-databases/tables/temporal-tables?view=sql-server-2017


4
因此,第一种方法可能更具可扩展性。由于将很少访问“归档”数据,因此可以优化数据库设计。而工作表保持小。根据复杂度,还应该只保存差异。建议使用记忆模式吗?
matcauthon 2012年

1
这将取决于您的使用情况,使用触发器填充表可能就足够了,然后提供一种选择回滚内容和回滚程度的方式。
jmoreno

您的答案有错别字(样式应该是样式)
geocodezip

7

一种想法是使用“仅插入数据库”。基本思想是您永远不会删除或更新数据

每个需要跟踪的表都有两datetimefromto。它们从NULL每个值开始(时间开始到时间结束)。当您需要“更改”行时,可以添加新行,同时to将上一行中的Now和更新为from要添加到的行Now

有关更多详细信息,请参见:

这项技术被称为AuditTrail管理遗留数据,并且它可以存储更改历史记录。

似乎已经发布了这种性质的问题:


不幸的是,这个问题似乎已经删除了:(
Douglas Gaskell

没问题,这是链接链接中的
Yusubov

2

我认为您可以为每个表使用触发器并在_history中维护数据(或者可以给任何名称),并且在主表的每个插入,更新,删除操作上都会触发触发器,并且可以将详细信息保存在此表中。如果您正在使用SQLite数据库,它也可用于SQLite数据库。

该机制对于大型项目也很有用。在此表中,您可以记录进行了更改的用户的信息以及更改的时间戳。然后,您可以将表恢复到符合您要求的任何时间戳记。

每个数据库都有其自己的编写和编码触发器的方式。如果您使用的是SQLite,请访问SQLite.org获取语​​法。对于其他数据库,您可以访问其官方站点。


1

您可能知道Sqlite数据库引擎。整个数据库保存在一个文件中。该api还支持虚拟文件系统,因此基本上您可以在任何地方以任何格式组织存储,只需响应特定文件偏移量的读取和写入操作即可。对此的可能应用可能是加密,压缩等。最好的部分是,容器层应该不了解数据库,sql或sqlite文件格式的任何信息,只需遵循xRead和xWrite回调即可。

想法之一是实现时光机功能。因此,任何xWrite操作都会保存将在“撤消”历史记录中覆盖的每个段,并且用户可以选择过去的日期以查看数据库所包含的内容(可能是只读模式)。我还没有有效的示例(在sqlite邮件列表中有关于它的讨论),但是可能其他引擎提供了VFS API,因此类似的事情是可能的。并且一旦实现,它就应该与任何复杂的数据库结构兼容。


您认为这种方法可用于大型项目吗?
matcauthon 2012年

我认为这可能会为大数据更改增加大量数据开销(显然,因为每个更改都应保存,尽管对旧版本进行压缩可以有所帮助)。除了您的架构之外,只要它适用于两个表,它就适用于二十个表。
Maksee 2012年

1

我们用于对数据库条目进行版本控制的方法是使用审核表。该表具有以下模式:

Seq      - Int      ' Unique identifier for this table
Event    - Char     ' Insert / Update / Delete
TblName  - Char     ' Table that had field value changed
FldName  - Char     ' Field that was changed
KeyValue - Char     ' delimited list of values for fields that make up the PK of table changed
UsrId    - Char     ' User who made the change
OldValue - Char     ' Old value (converted to character)
NewValue - Char     ' New value (converted to character)
AddTs    - DateTime ' When the change was made

然后,我们在要跟踪的表的“插入/更新/删除”上具有触发器。

优点:

  • 所有数据都在一个表中
  • 可以设置为跟踪表中的所有字段或特定字段
  • 易于在表格的每个字段上显示版本控制

缺点:

  • 将所有审核信息都放在一个表中会导致大量记录
  • 需要很多触发器

0

我正在为此做一个版本。对于每个记录,我都有一个插入日期,修改日期和活动记录布尔值标志。对于初始插入,“插入”和“修改”日期都设置为Now()(此示例在Access中),并且“活动记录”标志设置为true。然后,如果我修改该记录,则将整个内容复制到新记录,更改用户要更改的字段,我将“插入”日期保留为原始日期,并将“修改日期”更改为Now()。然后,将原始记录的“活动记录”标志翻转为false,将新记录的翻转为true。我还有一个ModifiedRecordsParentID字段,用于保存原始记录的标识。

然后,如果我什至需要查询,我可以只返回记录在哪里,ActiveRecord = true而我只会得到最新的信息。


不需要ActiveRecord标志。MAX(*)行应始终为当前记录。恢复到以前的版本只需将所述行再次插入表中。
反转

我不知道如何使选择的工作,但现在,我们在调用了这一点,我想这个问题,有一个想法,hmmmm
布拉德

通常,MAX(column_name)在表的列中选择最大值。要选择整行,只需一个简单的select top 1 order by id descending操作即可。
反转

是的,它适用于简单的单个记录,但是我的表是子记录的集合,需要立即选择这些子记录,但可以单独进行修改。只是稍微复杂一点。
Brad 2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.