我的应用程序为在线商店的客户提供服务。我的数据库中的一个表是"产品"它有一个列" In_Stock"。这是一个布尔(bit(1))列。我的客户发送其产品目录的数据馈送,每个客户都有自己的此表版本。我想跟踪此库存列中的更改,这是对......的影响。
11/13/2016 true
12/26/2016 false
01/07/2017 true
就这样,当我进行一些审核时,我可以在给定的时间段内看到给定产品的状态。
我最好能做到这一点吗?
创建一个单独的历史表并通过一个布尔列的触发器更新它似乎有点过分。历史专栏是否足够?我可以用某种JSON字符串保存数据。
答案 0 :(得分:1)
对不起,任何可行的解决方案都需要第二张表。
一个这样的解决方案是Version Normal Form(vnf),这是2nf的一个特例。考虑包含布尔字段的表(假设它已正确标准化为至少3nf)。现在,您要跟踪对布尔字段所做的更改。一种方法是通过添加 EffectiveDate 列将行转换为版本然后,而不是更新行,在日期字段中写入当前日期的新行(或更新布尔字段是否保持不变)。
这允许跟踪字段,每次更改字段时都会有新版本。但是存在严重的缺点,其中不仅仅是行不再是实体,而是实体的版本。这使得无法使用此表的外键作为那些想要引用实体的外键。
但仔细看看设计。在更改之前,您有一个良好的规范化表,没有跟踪更改。添加 EffectiveDate 列后,发生了微妙的变化。除了布尔字段之外的所有字段都像以前一样仅依赖于PK。布尔字段不仅依赖于PK,还依赖于新的日期字段。它不再是2nf。
规范化表需要将布尔字段和日期字段移动到新表:
create table NewTable(
EntityID int not null references OriginalTable( ID ),
EffDate date not null,
TrackedCol boolean,
constraint PK_NewTable primary key( EntityID, EffDate )
);
将新行插入原始表时插入第一个版本。从那时起,只有当对原始表的更新改变了布尔字段的值时,才会添加另一个版本。
Here是之前的答案,其中包含用于获取版本化数据的当前值和任何过去值的查询。我在这里多次讨论过这个设计。
此外,还有一种方法可以构建设计,因此不需要更改应用程序代码。也就是说,重新设计对现有代码完全透明。上面链接的答案包含另一个指向更多文档的链接,以显示如何完成。
答案 1 :(得分:0)
我会触发事情。但是不要复制整个列 - 获取唯一列id,记录时间戳和布尔值。 有时拥有好的日志是无价的:)
答案 2 :(得分:0)
我为此编写了一个audit trail module,它基本上复制了表格,为每一行添加了一些信息,并保持原始数据表不受影响,除了触发器。