Mysql RDBMS建模:具有极端历史版本控制的多对多
您有两个表,Mysql RDBMS建模:具有极端历史版本控制的多对多,mysql,oracle,postgresql,database-design,rdbms,Mysql,Oracle,Postgresql,Database Design,Rdbms,您有两个表,foo和bar,它们具有M:N关系 您希望维护foo和bar的极端历史版本,以及它们之间的关系,例如: 在Foo中插入一行,然后在Bar中插入一行,然后在FooBar中插入一行,将两者链接在一起。您应该能够及时回顾并看到Foo中的行曾经是独立的,就像Bar中的行一样 然后将另一行插入Bar,并在FooBar中插入一行,将第二个Bar链接到第一个foo。您应该能够及时回顾并看到foo行仅链接到第一个bar行 然后更新foo行的一个属性。您应该能够及时回顾并看到Bar中的两行曾经链接到具
foo
和bar
,它们具有M:N
关系
您希望维护foo
和bar
的极端历史版本,以及它们之间的关系,例如:
Foo
中插入一行,然后在Bar
中插入一行,然后在FooBar
中插入一行,将两者链接在一起。您应该能够及时回顾并看到Foo
中的行曾经是独立的,就像Bar
中的行一样Bar
,并在FooBar
中插入一行,将第二个Bar
链接到第一个foo
。您应该能够及时回顾并看到foo
行仅链接到第一个bar
行foo
行的一个属性。您应该能够及时回顾并看到Bar
中的两行曾经链接到具有上一个属性的foo
行DDL
Foo
--------------
foo_id INT --sequence generated
foo_version_id INT UNIQUE --sequence generated
foo_name VARCHAR
active INT CHECK (active in (0,1))
CONSTRAINT PRIMARY_KEY (foo_id, foo_version_id)
Bar
--------------
bar_id INT --sequence generated
bar_version_id INT UNIQUE --sequence generated
bar_name VARCHAR
active INT CHECK (active in (0,1))
CONSTRAINT PRIMARY_KEY (bar_id, bar_version_id)
FooBar
--------------
foo_version_id FK to foo.foo_version_id
bar_version_id FK to bar.bar_version_id
CONSTRAINT PRIMARY KEY (foo_version_id, bar_version_id)
DML
Foo
--------------
foo_id INT --sequence generated
foo_version_id INT UNIQUE --sequence generated
foo_name VARCHAR
active INT CHECK (active in (0,1))
CONSTRAINT PRIMARY_KEY (foo_id, foo_version_id)
Bar
--------------
bar_id INT --sequence generated
bar_version_id INT UNIQUE --sequence generated
bar_name VARCHAR
active INT CHECK (active in (0,1))
CONSTRAINT PRIMARY_KEY (bar_id, bar_version_id)
FooBar
--------------
foo_version_id FK to foo.foo_version_id
bar_version_id FK to bar.bar_version_id
CONSTRAINT PRIMARY KEY (foo_version_id, bar_version_id)
下面是这三种情况的伪代码。我已将这些作为程序加以实施
对于情况#1,这将导致4个DML操作,将两个独立的foo
和bar
链接在一起,不包括前两行:
Insert the first foo row
Insert the first bar row
Update the first foo row and set active to 0.
Insert a new foo row with the same foo_id, foo_name, but new foo_version_id
Update the first bar row and set active to 0
Insert a new bar row and with the same bar_id, bar_name, but new bar_version_id
Insert a row into foo_bar with the foo_version_id and bar_version_id from the newly created active foo and bar rows.
对于情况#2,这将导致9个DML操作,将新的条链接到链接到第一个条的foo
,不包括第一行:
Insert the second bar row
Update the active foo and set active to 0
Insert a new foo row with same foo_id, foo_name, but new foo_version_id
Update the first active bar and set active to 0
Insert a new bar row with same bar_id, bar_name, but new bar_version_id
Update the second active bar and set active to 0
Insert a new bar row with same bar_id, bar_name, but new bar_version_id
Insert a row into foo_bar with the foo_version_id and bar_version_id from the foo and first bar.
Insert a row into foo_bar with the foo_version_id and bar_version_id from the foo and second bar.
对于情况#3,这将导致8个DML操作来更新链接到两个条的foo
上的属性:
Update the active foo and set active to 0
Insert a new foo row with same foo_id, but new foo_version_id, foo_name
(repeat from case #2 starting at line 4)
SQL
Foo
--------------
foo_id INT --sequence generated
foo_version_id INT UNIQUE --sequence generated
foo_name VARCHAR
active INT CHECK (active in (0,1))
CONSTRAINT PRIMARY_KEY (foo_id, foo_version_id)
Bar
--------------
bar_id INT --sequence generated
bar_version_id INT UNIQUE --sequence generated
bar_name VARCHAR
active INT CHECK (active in (0,1))
CONSTRAINT PRIMARY_KEY (bar_id, bar_version_id)
FooBar
--------------
foo_version_id FK to foo.foo_version_id
bar_version_id FK to bar.bar_version_id
CONSTRAINT PRIMARY KEY (foo_version_id, bar_version_id)
给定一个已知的foo\u id
,我可以在foo版本id
和bar版本id
上左键加入foo
,bar
,并查看所讨论的特定foo的所有可能历史状态
select f.foo_id, f.foo_version_id, f.foo_name, b.bar_id, b.bar_version_id, b.bar_name
FROM foo f, foo_bar fb, bar b
WHERE 1 = 1
AND f.foo_version_id = fb.foo_version_id (+)
AND fb.bar_version_id = b.bar_version_id (+)
ORDER BY f.foo_version_id, b.bar_version_id
;
foo_id | foo_version_id | foo_name | bar_id | bar_version_id | bar_name
1 | 1 | a | | | -- 1) independent foo
1 | 2 | a | 1 | 2 | b -- 2) link foo to first bar
1 | 3 | a | 1 | 4 | b -- 3) link second bar to foo
1 | 3 | a | 2 | 5 | b2 -- 3) link second bar to foo
1 | 4 | A | 1 | 6 | b -- 4) rename foo_name to A
1 | 4 | A | 2 | 7 | b2 -- 4) rename foo_name to A
您需要一个时态数据库,即支持SQL:2011时态(或类似的专有系统)的数据库
据我所知,没有开源数据库支持这一点。我一直在缠着那些时髦的家伙做这件事
这意味着你需要拿出一些现金。以下数据库支持它:
IBM DB2 10+
Oracle 12c
MS SQL Server 2016您能解释一下为什么需要这一级别的历史详细信息吗?@RickJames我有一项业务要求,要求用户能够快速返回到用户过去曾经拥有的foo
和bar
的任何配置。在这种情况下,根据定义,一个foo
包括所有相关的条
,反之亦然。更改当前foo
上的属性会更改相关条的性质,反之亦然。此需求的“所有者”是否理解生成的数据库系统的构建和维护成本将是原来的10倍?是否会“折衷”为“闪回昨天的一个转储”够了吗?你说的是一个临时数据库,它是在(ISO/IEC 9075:201)中添加到标准中的。据我所知,到目前为止只有(部分)这件事。如果你想维持FK关系,那么你不会比这更好。如果您不介意不强制执行FK关系,那么它会变得容易得多。。。