任何人都可以建议在DB中版本化ATTRIBUTE(而不是OBJECT)数据的方法

时间:2015-08-22 09:31:51

标签: database version temporal-database 6nf

以MySQL作为示例数据库来执行此操作(虽然我不限于此阶段的关系风格)和用于模型/数据库交互的Java风格语法。

我希望能够在用户编辑对象时允许对各个列值(及其相应类型)进行版本控制。这主要是为了减少频繁编辑复杂对象所需的存储量。

一个简单的例子可能是

 - Food (Table)
     - id (INT)
     - name (VARCHAR(255))
     - weight (DECIMAL) 

所以我们可以在数据库中插入一个看似......的对象。

Food banana = new Food("Banana",0.3);

给我们

+----+--------+--------+
| id |  name  | weight |
+----+--------+--------+
|  1 | Banana | 0.3    |
+----+--------+--------+

如果我们想要更新我们可能使用的重量

banana.weight = 0.4;
banana.save();

+----+--------+--------+
| id |  name  | weight |
+----+--------+--------+
|  1 | Banana | 0.4    |
+----+--------+--------+

显然,这会覆盖数据。

我可以在此表中添加修订列,可以在保存项目时增加,并设置组合id / version的组合键,但这仍然意味着为每个修订版本存储此对象的所有属性

- Food (Table)
      - id (INT)
      - name (VARCHAR(255))
      - weight (DECIMAL) 
      - revision (INT)

+----+--------+--------+----------+
| id |  name  | weight | revision |
+----+--------+--------+----------+
|  1 | Banana | 0.3    |        1 |
|  1 | Banana | 0.4    |        2 |
+----+--------+--------+----------+

但在这种情况下,我们将存储关于每个项目的每一条数据。如果用户对较大的对象进行少量修改,而文本字段甚至BLOB数据可能是对象的一部分,则这不是非常有效的。

我真正喜欢的是能够选择性地存储数据,因此权重可以单独保存在一个单独的数据库中,这样就可以引用表,行和列它与之相关。

然后可以将其与表的VIEW一起粉碎,这可以将各个列数据的任何后续版本强加到混合中以创建最新版本,但不需要为每个小版本存储所有数据。

+----+--------+--------+
| id |  name  | weight |
+----+--------+--------+
|  1 | Banana | 0.3    |
+----+--------+--------+

+-----+------------+-------------+-----------+-----------+----------+
| ID  | TABLE_NAME | COLUMN_NAME | OBJECT_ID | BLOB_DATA | REVISION |
+-----+------------+-------------+-----------+-----------+----------+
| 456 | Food       | weight      |         1 | 0.4       |        2 |
+-----+------------+-------------+-----------+-----------+----------+

不确定将任何数据存储为blob的成功与否然后CAST回到原始的DTYPE可能是,但是我想在这里发明功能,为什么不坚持下去。

这种存储方法也相当危险,因为表名和列名完全可以改变,但希望这至少概括了我所想的那种行为。

1 个答案:

答案 0 :(得分:1)

6NF中的表有一个CK(候选键)(在SQL中为PK),最多只有一个列。基本上6NF允许每个pre-6NF表的列更新时间/版本和值以无异常的方式记录。您可以通过删除非素数列来分解表,同时添加带有它的表以及旧的CK列。对于临时/版本控制应用程序,您进一步添加时间/版本列,新CK是旧的加上它。

添加一列时间/任何时间间隔(在SQL开始时间和结束时间列中)而不是时间到CK允许通过记录最长的不间断时间段或其他维度来进行数据压缩,通过该时间段,列具有相同的值。一个查询由原始CK加上您想要的值的时间。你不需要这个用于你的目的,但是标准化为6NF的初始过程和添加时间/任何列应该在时间教程中解释。

阅读temporal databases(同时处理"有效"时间和时间间隔的数据,但也"事务和#34;数据库更新的时间/版本)和6NF和它在它们中的作用。 (Snodgrass / TSQL2很糟糕,Date / Darwen / Lorentzos很好,SQL也有问题。)

您最终建议的表格是EAV的示例。这通常是一种反模式。它将数据库编码到一个或多个有效元数据的表中。但由于DBMS不知道你失去了很多功能。如果DDL足以管理具有您需要的列的表,则不会调用EAV。只需在每个数据库中声明适当的表。这实际上是一个数据库,因为您希望事务影响两者。从那个链接:

  

您正在使用DBMS反模式EAV。您是(trying to) build part of a DBMS into your program + database. DBMS已经存在来管理数据和元数据。使用它。

     

没有metatdata的类/表。 Just have attributes of movies be fields/columns of Movies.

     
    

人们需要使用EAV"因此每种实体类型都可以     扩展自定义字段"是错的。只需通过电话实现     更新元数据表有时而不是只更新常规     tables:DDL而不是DML。