Sql 如何为n:m关系设计历史记录
问题: 我有一个表a和另一个表B之间的n:m关系,它需要有这个关系的完整历史,换句话说,我必须能够重现过去任何一点的状态 想法: 我的第一次尝试是通过插入一个虚拟表来将to关系分解为1:m和m:n关系,以便在发生某些更改时在任何给定时间保存该关系的状态。像这样:Sql 如何为n:m关系设计历史记录,sql,plsql,many-to-many,Sql,Plsql,Many To Many,问题: 我有一个表a和另一个表B之间的n:m关系,它需要有这个关系的完整历史,换句话说,我必须能够重现过去任何一点的状态 想法: 我的第一次尝试是通过插入一个虚拟表来将to关系分解为1:m和m:n关系,以便在发生某些更改时在任何给定时间保存该关系的状态。像这样: TABLE A TABLE B -------- --------- ID INT ID INT TABLE HIST
TABLE A TABLE B
-------- ---------
ID INT ID INT
TABLE HIST TABLE CROSS_REF
---------- -----------------
ID INT REF_B_ID INT
REF_A_ID INT REF_HIST_ID INT
VERSION TIMESTAMP
Pro:查询所需信息很容易。缺点:这种尝试会产生大量冗余数据,尤其是当B端较大且只有微小变化时。例如在用例Company-Employee中
第二种方法是维护两个n:m关系,一个用于当前状态,另一个用于发生的更改
TABLE A TABLE B
-------- ---------
ID INT ID INT
TABLE CHANGES TABLE CROSS_REF
---------- -----------------
REF_A_ID INT REF_A_ID INT
REF_B_ID INT REF_B_ID INT
ACTION_TIME TIMESTAMP
ACTION_TYPE VARCHAR
赞成:没有冗余数据。缺点:很难查询过去特定时间点的状态
问题
你对我如何为这个应用程序设计数据模型还有什么建议吗?
如果没有更好的办法解决这个问题:我应该走哪条路?还是主要取决于给定的用例,如上面描述的示例?
如果我采用第二种方法,那么在过去某个特定时间点的状态查询会是什么样子?我能够在客户端解决这个问题,但我也想知道数据库端的解决方案。PL/SQL也是可行的
这个常用的模型怎么样
create table cross_ref
( a_id references a
, b_id references b
, from_ts timestamp
, to_ts timestamp
, primary key (a_id, b_id, from_ts)
);
注意,我和你一样使用时间戳;通常我会使用date谢谢你的建议,这的确是个好主意。最后,我想将JPA用于ORM,因此使用这种方法可能有点棘手,但这是进一步考虑的一个良好起点Tony,我与OP有相同的问题。如果我理解你的答案,你建议在某个时间点使用一个单独的表来保持关系。我不明白从哪里到哪里?您是否使用它们来跟踪记录的有效性?此外,我需要存储整个记录的历史记录,而不仅仅是关系,我已经在几个地方读过了,我应该使用创建一个只存储更新列的历史记录表的方法。如果要添加您的解决方案,我是否需要两个单独的表,或者我是否可以使用同一个表并只添加额外的字段?有更好的解决方案吗case@eestein,from_ts和to_ts列的目的是能够根据OP的要求再现过去任何一点的状态。因此,您可以从交叉引用中查询select b_id,其中a_id=1,日期为“2015-01-01”,介于from_ts和to_ts之间,以找出在该日期与a关联的b。@TonyAndrews Ok,我目前不需要该项。。。您认为将您的解决方案与我提到的解决方案合并是我的最佳选择吗?我将有一个带有tb1_id、tb2_id、column_name以及新值和旧值列的表。你的想法是什么?感谢您的时间:至于存储历史记录,这取决于您的需求。对于安全审计跟踪用户,Joe在2015年7月29日11:23将员工123的工资更改为20000,您可以使用一个通用表,其中包含表名、列名、键、旧值、新值、用户、日期时间等行。但如果是为了回答商业问题,那么一份包含所有原始列以及起始/截止日期的历史记录可能会更好。有时这会被合并,即当前记录也在仅历史记录的表中,from=当有效时,to=空