0

以 MySQL 作为示例 DB 来执行此操作(尽管在此阶段我不限于关系风格)和用于模型/数据库交互的 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 可能有多成功,但我想既然我在这里发明了功能,为什么不发疯。

这种存储方法也相当危险,因为表名和列名完全可以更改,但希望这至少概述了我正在考虑的那种行为。

4

1 回答 1

2

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

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

阅读时态数据库(既处理“有效”数据,即时间和时间间隔,也处理“事务”时间/数据库更新版本)和 6NF 及其在其中的作用。(Snodgrass/TSQL2 不好,Date/Darwen/Lorentzos 好,SQL 有问题。)

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

您正在使用 DBMS 反模式 EAV。您正在(尝试)将 DBMS 的一部分构建到您的程序 + 数据库中。DBMS 已经存在以管理数据和元数据。用它。

没有元数据的类/表。只是让电影的属性成为电影的字段/列。

需要使用 EAV“因此每个实体类型都可以使用自定义字段进行扩展”的概念是错误的。只需通过有时更新元数据表的调用来实现,而不仅仅是更新常规表:DDL 而不是 DML。

于 2015-08-23T13:18:05.900 回答