跟踪更改历史记录的数据库结构

时间:2008-09-26 20:00:24

标签: ruby-on-rails database-design

我正在将项目管理系统的数据库设计作为个人项目,我遇到了麻烦。

我想实现一个票务系统,我希望票证看起来像tickets in Trac。我会用什么结构来复制这个系统? (我在任何系统上都没有成功安装trac,所以我真的看不到它在做什么)

注意:尝试在任何版本中存储或显示故障单都没有意义。我只需要一个变化的历史。我不想存储额外的数据。另外,我在文本字段中使用序列化数组实现了这样的功能。我不想再将其作为解决方案来实现。

编辑:我只关注数据库结构。触发/回调不是真正的问题。

6 个答案:

答案 0 :(得分:15)

我使用“瘦”设计实现了纯记录更改数据:

RecordID  Table  Column  OldValue  NewValue
--------  -----  ------  --------  --------

您可能不想使用“表格”和“列”,而是使用“对象”和“属性”等等,具体取决于您的设计。

这具有灵活性和简单性的优点,但是以查询速度为代价 - “表”和“列”列上的聚簇索引可以加速查询和过滤。但是,如果您要在桌面或对象级别频繁在线查看更改日志,您可能需要设计更平坦的内容。

编辑:有几个人正确地指出,使用此解决方案,您无法将变更集合在一起。我在上面的表中忘了这一点 - 我使用的实现还有一个带有日期时间,用户和其他信息的“Transaction”表,以及一个“TransactionID”列,所以设计看起来像这样:

CHANGE LOG TABLE:
RecordID  Table  Column  OldValue  NewValue  TransactionID
--------  -----  ------  --------  --------  -------------

TRANSACTION LOG TABLE:
TransactionID  UserID  TransactionDate
-------------  ------  ---------------

答案 1 :(得分:3)

您是否正在使用这样的数据库机制?

   CREATE OR REPLACE TRIGGER history$yourTable
        BEFORE UPDATE ON yourTable
        FOR EACH ROW
        BEGIN
            INSERT INTO
                history
            VALUES
                (
                :old.field1,
                :old.field2,
                :old.field3,
                :old.field4,
                :old.field5,
                :old.field6
                );
        END;
    /
    SHOW ERRORS TRIGGER history$yourTable

答案 2 :(得分:3)

我做了这样的事。我有一个名为LoggableEntity的表,其中包含:ID(PK)。

然后我有EntityLog表,其中包含有关对loggableentity(记录)所做更改的信息:ID(PK),EntityID(FK到LoggableEntity.ID),ChangedBy(进行更改的用户名),ChangedAt(更改时的smalldatetime)发生了),类型(枚举:创建,删除,更新),详细信息(包含已更改内容的备注字段 - 可能是带有序列化详细信息的XML)。

现在我要跟踪的每个表(实体)都是从LoggableEntity表中“派生”的 - 这意味着例如Customer有FK到LoggableEntity表。

现在,只要对客户记录进行了更改,我的DAL代码就会负责填充EntityLog表。每当它看到实体类是一个可记录实体时,它就会将新的更改记录添加到实体日志表中。

所以这是我的表结构:

+------------------+           +------------------+
| LoggableEntity   |           | EntityLog        |
| ---------------- |           | ---------------- |
| (PK) ID          | <--+      | (PK) ID          |
+------------------+    +----- | (FK) LoggableID  |
        ^                      |      ...         |
        |                      +------------------+
+------------------+
| Customer         |
| ---------------- |
| (PK) ID          |
| (FK) LoggableID  |
|      ...         |
+------------------+

答案 3 :(得分:2)

至于不存储大量额外数据,我想不出有什么好方法可以做到这一点。您必须存储每个修订版才能看到更改。

这是我见过的一个解决方案,虽然我不确定它是否是最好的解决方案。有一个主键,比如说id指向特定修订版。还有ticket_numberrevision_date个字段。修改故障单时,ticket_number不会更改,但idrevision_date会更改。然后,根据上下文,您可以使用groupwise max获取特定修订或特定故障单的最新修订。

答案 4 :(得分:1)

我会说创建某种事件监听类,每当你的系统内发生某些事情时你都会ping它。将事件的描述放在数据库中。

它应该存储基本的谁/ what / where / when / what info。

通过该项目事件表进行排序可以获得您想要的信息。

答案 5 :(得分:0)

一种可能的解决方案是将故障单的副本与进行更改的用户一起存储在历史记录表中。

但是,这将存储大量额外数据,并需要大量处理来创建Trac显示的视图。