如何使用一对多关系保持桌面上的记录历史记录?

时间:2012-06-26 14:12:54

标签: postgresql database-design one-to-many

我有一个“服务”表,用于详细说明我们提供的服务。需要记录的数据包括几个小的一对多关系(都具有对service_id的外键约束),例如:

service_owners -- user_ids responsible for delivery of service
service_tags -- e.g. IT, Records Management, Finance
customer_categories -- ENUM value
provider_categories -- ENUM value
software_used -- self-explanatory

我遇到的问题是我想保留一个服务更新的历史记录,我在表上使用了一个更新触发器,它执行插入到与原始列匹配的历史记录表中。但是,如果使用上述数据的规范化方法,并且每个一对多关系使用单独的表和外键,则在服务历史记录中将无法识别这些表的任何更新。

有没有人有任何建议?似乎我需要在服务表中存储子密钥以维护服务历史记录的完整性。分隔文本字段在这里是一个有效的方法,或者,因为我使用postgreSQL,也许数组也是一个有效的选项?虽然这些感觉有点脏!

感谢。

2 个答案:

答案 0 :(得分:2)

如果你的表是:

create table T (
    ix int identity primary key,
    val nvarchar(50)
)

您的历史记录表是:

create table THistory (
    ix int identity primary key,
    val nvarchar(50),
    updateType char(1), -- C=Create, U=Update or D=Delete
    updateTime datetime,
    updateUsername sysname
)

然后你只需要在所有感兴趣的表上放置一个更新触发器。然后,您可以了解历史中任何一个表的状态,以确定当时的关系。

答案 1 :(得分:2)

我尽量避免在任何数据库中使用数组。

我不喜欢更新,因为你在这里说的确切原因......你丢失信息,因为它已经过度写了。我的回答非常简单......不要更新。不确定你是否处于可以实现的地步......但是如果可以,我建议使用主表本身来存储历史记录(不需要第二组历史表)。

在主标题表中添加一个名为“active”的列。这可以是字符或位(0表示关闭,1表示打开)。然后它有点触发魔法...当执行更新时,在表中插入一行与被覆盖状态为“0”(或非活动)的记录相同,然后更新现有行(这进程使活动记录上的ID列保持不变,新插入的记录是具有新ID的非活动记录。

这样就不会丢失任何数据(诚然,你存储了不少行...),并且可以使用select = 0的选项轻松查看历史记录。

这里的痛苦在于,如果您正在处理已经实现的内容...每个现有的查询都需要更新以包含对活动列的检查。如果您正在设计一个新系统,这个解决方案很容易实现,但如果它是一个长期的应用程序,那就太痛苦了。遗憾的是,现有报告将包括off和on记录(不会抛出错误),直到您可以修改where子句