Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.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
Mysql RDBMS建模:具有极端历史版本控制的多对多_Mysql_Oracle_Postgresql_Database Design_Rdbms - Fatal编程技术网

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

  • 虽然我能够实现这一点,但我的解决方案相当单调乏味,并且在一次更新/插入中会导致大量DML操作。在Baz和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

    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关系,那么它会变得容易得多。。。