1

我有一个存储业务联系人和相关信息的表。

目前,每天都会将所有联系人的副本保存在表格中。表结构如下所示:

Date        CompanyName          Description      Address        Industry
20130416    Alpha Corp           bla bla bal      6100 main st.  Finicial 

20130417    Alpha Corp           bla bla bal      6100 main st.  Finicial 
20130417    Beta Corp            bla bla bal      6500 main st.  Consumer

20130418    Alpha Corp           bla bla bal      6120 main st.  Finicial 
20130418    Beta Corp            bla bla bal      6500 main st.  Consumer

这说明了添加 20130417 "Beta Corp" 和修改 20130418 "Alpa corp" 时会发生什么。

我想将其更改为具有审计跟踪功能。目前我想到的是一个存储所有当前条目的表(引入新字段 CompanyID int auto-intrement)

CompanyID CompanyName Description Address Industry

还有一张表来存储所有的历史变化

CompanyID CompanyName Description Address Industry ChangeTime Action User

大多数查询将是从今天开始获取联系人列表,这在新架构下将很容易,但我仍然希望能够执行诸如“获取截至 20130416 的联系人列表”之类的查询,这应该返回 1 行。而且通过当前条目和更改日志来构建历史数据感觉相当肮脏。

在类似的情况下你会怎么做?和推理?

最好的,

4

4 回答 4

3

审计跟踪通常可以识别谁更改了什么。您正在寻找完全不同的东西。您希望您的数据库能够回答诸如select * from table_name where (data appears as it did on 2013-01-15);.

据我所知,Richard Snodgrass 发表了最早使用 SQL 解决此类问题的综合著作。他将面向时间的数据库(和表)分为这些类别。

  • 有效时间表:这些时间表捕捉了“不断变化的现实的历史”。
  • 事务时间表:它们捕获“变化表的状态序列”。
  • 双时态表:这些实现了有效时间和事务时间表。

我认为您正在寻找双时态表。

他的《用 SQL 开发面向时间的数据库应用程序》一书可从他在亚利桑那大学的教师网页上以 PDF 格式下载。因为它是免费的,所以在你把自己挖到一个洞之前,没有理由不浏览它。仔细阅读代码以了解完整性约束。(弄错了,你的数据库几乎一文不值。)

于 2013-04-17T16:49:19.020 回答
0

我使用过必须维护审计历史的数据库。为此,有一个名为“Timeframe ID”的字段。如果此字段的值为 -1,则表示该记录是过去的。如果为 0,则记录是当前的。在某些情况下,它会是 1,表示它是未来的记录(这种情况很少见)。

这些表还有一个“修改”日期字段。因此,如果用户进行更新,您只需将当前 Timeframe 0 记录更新为 -1 并插入一个包含修改后数据的新行。通过这种方式,您可以知道谁更改了什么以及何时更改。或者,在您每天更新数据的情况下,修改日期将是加载记录的日期。

希望这可以帮助。

于 2013-04-17T14:41:08.980 回答
0

我认为你在正确的轨道上约翰尼。我的建议是像您建议的那样拆分表格。

Travis 的解决方案可能工作正常,但考虑到历史快照会随着时间的推移变得非常大。如果将它们分开,当天的查询将运行得很快。如果你把它们放在一起,随着时间的推移,查询自然会变得越来越慢(当然可能需要一段时间才能注意到)。

Travis 提出的将修订 ID 与公司 ID 配对的想法很好。过去我将其称为“快照”ID。我在表中有一个快照 ID,然后是另一个包含我可以加入的快照详细信息的表。

例如:

公司表:

CompanyID, CompanyName, Description, Address, Industry

公司历史表(其中 Snapshot ID 和 Company ID 代表您的密钥):

SnapshotID, CompanyID, CompanyName, Description, Address, Industry

快照表:

SnapshotID, CreateDate, CreateDateTime

我强烈考虑将创建快照的时间归零,以使查询更容易一些。如果它们真的只代表一天,那么时间就会变得烦人。您仍然可以存储它以查看它的实际完成时间。

于 2013-04-17T16:52:27.397 回答
0

有些事情要考虑。首先,审计的目的是什么?审计不同于维护面向时间的数据。如果您正在审核,您将需要能够撤消更改的信息。因此,保存旧数据很重要,但保存更改发生的日期以及更改的人员或应用程序也很重要。这样,如果您在周三和周五发布应用程序的新版本,则会发现一个错误,它改变了很多不应该改变的东西;您确切地知道该应用程序从周三到周五更改了哪些记录,并且可以轻松修复不良变化。真正的审计应该总是通过触发器而不是应用程序来处理。

历史数据不同,你这样做是因为你需要知道某事在某个时间点的状态。例如,在订单详细信息表中,您可能希望存储订单时商品的价格,而不是一年后查询记录时的价格。在这种情况下,您可以将所有内容存储在一个表中,如果您有一个大型数据库分区,则按时间进行分区。这涉及在每次数据更改时将应用程序放入一个新行中。如果您这样做,您可能希望创建一个仅显示当前记录的视图。事实上,我会更改表的名称并使用您当前的表名创建视图,以避免破坏任何现有代码。这将帮助您避免在针对此表编写新代码时忘记输入仅获取活动数据的限定符。

或者您可以做两个表,其中旧值通过触发器移动(甚至不要考虑通过应用程序进行移动,为此必须处理任何可能的表更改,并且触发器是确保发生这种情况的唯一地方) 当数据发生变化时。如果您这样做,那么您可能希望创建一个将两个表联合在一起的视图,以便您可以查询所有数据。

于 2013-04-17T17:22:55.867 回答