Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何为n:m关系设计历史记录_Sql_Plsql_Many To Many - Fatal编程技术网

Sql 如何为n:m关系设计历史记录

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

问题:

我有一个表a和另一个表B之间的n:m关系,它需要有这个关系的完整历史,换句话说,我必须能够重现过去任何一点的状态

想法:

我的第一次尝试是通过插入一个虚拟表来将to关系分解为1:m和m:n关系,以便在发生某些更改时在任何给定时间保存该关系的状态。像这样:

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=空