gpt4 book ai didi

mysql - RDBMS 建模 : Many to Many with Extreme Historical Versioning

转载 作者:可可西里 更新时间:2023-11-01 08:40:03 25 4
gpt4 key购买 nike

您有两个表,foobar,它们具有 M:N 关系。

您想维护 foobar 的相当极端的历史版本,以及它们之间的关系,例如:

  1. 你在 Foo 中插入一行,然后在 Bar 中插入一行,然后在 FooBar 中插入一行链接两人在一起。您应该能够及时回顾并看到 Foo 中的行曾经是独立的,Bar 中的行也是如此。

  2. 然后,您将另一行插入到 Bar 中,并在 FooBar 中插入一行,将第二个 bar 链接到第一个 >富。您应该能够及时回顾并看到 foo 行仅链接到第一个 bar 行。

  3. 然后您更新 foo 行的属性之一。您应该能够及时回顾并看到 Bar 中的两行都曾经链接到具有前一个属性的 foo 行。

虽然我能够实现这一点,但我的解决方案相当乏味,并且会导致针对单个更新/插入的大量 DML 操作。在 Bar 和 Baz 之间添加一个带有 M:N 的 Baz 表会显着增加 DML 的数量。是否有比以下方法更好地完成此任务的标准方法?

这是我的解决方案:


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

以下是三种情况的伪代码。我已将这些作为程序实现。

对于案例#1,这导致 4 个 DML 操作将两个独立的 foobar 链接在一起,不包括前两个行:

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 操作将新的 bar 链接到 foo,而 foo 链接到第一个 bar,不包括第一行:

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 操作来更新链接到两个 barsfoo 上的属性:

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_id,我可以在 foo_version_id 上加入 foofoo_barbar bar_version_id 并查看所讨论的特定 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 Temporal 的数据库(或类似的专有系统)

据我所知,没有开源数据库支持这一点。一段时间以来,我一直在缠着 Posgres 的人去做这件事。

这意味着您需要支付一些现金。以下数据库支持它:

IBM DB2 10+
甲骨文 12c
微软 SQL Server 2016

关于mysql - RDBMS 建模 : Many to Many with Extreme Historical Versioning,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35399312/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com