谁能建议一种在数据库中对属性(而不是对象)数据进行版本控制的方法
Can anyone suggest a method of versioning ATTRIBUTE (rather than OBJECT) data in DB
以 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 |
+----+--------+--------+
显然这会覆盖数据。
我可以向这个 table 添加一个修订列,它可以随着项目的保存而递增,并设置一个组合键 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 数据可能是对象的一部分的较大对象进行较小的修改,这并不是非常有效。
我真正想要的是能够选择性地离散存储数据,这样权重就可以单独保存在单独的数据库中,这样就可以引用 table ,它涉及的行和列。
然后可以将其与 table 的 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 的成功率如何,但认为既然我在这里发明了功能,为什么不发疯呢。
这种存储方法也相当危险,因为 table 和列名完全可以更改,但希望这至少概述了我正在考虑的那种行为。
6NF中的一个table有一个CK(候选键)(在SQL中是一个PK)并且最多有一个其他列。本质上,6NF 允许每个 pre-6NF table 的列的更新 time/version 和以无异常方式记录的值。您通过删除非主列同时添加 table 和旧 CK 的列来分解 table。对于 temporal/versioning 应用程序,您进一步添加一个 time/version 列,新的 CK 是旧的加上它。
向 CK 添加一列 time/whatever 间隔(在 SQL 开始时间和结束时间列中)而不是时间允许通过记录最长的不间断时间段或其他时间来进行一种数据压缩列具有相同值的维度。一个查询由原始 CK 加上您想要其值的时间。你不需要这个用于你的目的,但是标准化到 6NF 的初始过程和添加 time/whatever 列应该在临时教程中解释。
阅读有关 temporal databases(它处理 "valid" 时间和时间间隔的数据以及 "transaction" times/versions 数据库更新)和 6NF 及其作用在他们中。 (Snodgrass/TSQL2 不好,Date/Darwen/Lorentzos 好,SQL 有问题。)
您最终建议的 table 是 EAV 的示例。这通常是一种反模式。它将数据库编码为一个或多个 table 有效元数据。但是由于 DBMS 不知道您失去了它的大部分功能。如果 DDL 足以管理包含您需要的列的 table,则不需要 EAV。只需在每个数据库中声明适当的 tables。这实际上是一个数据库,因为您希望交易会影响两者。从那个 link:
You are using a DBMS anti-pattern EAV. You are (trying to) build part of a DBMS into your program + database. The DBMS already exists to manage data and metadata. Use it.
Do not have a class/table of metatdata. Just have attributes of movies be fields/columns of Movies.
The notion that one needs to use EAV "so every entity type can be
extended with custom fields" is mistaken. Just implement via calls
that update metadata tables sometimes instead of just updating regular
tables: DDL instead of DML.
以 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 |
+----+--------+--------+
显然这会覆盖数据。
我可以向这个 table 添加一个修订列,它可以随着项目的保存而递增,并设置一个组合键 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 数据可能是对象的一部分的较大对象进行较小的修改,这并不是非常有效。
我真正想要的是能够选择性地离散存储数据,这样权重就可以单独保存在单独的数据库中,这样就可以引用 table ,它涉及的行和列。
然后可以将其与 table 的 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 的成功率如何,但认为既然我在这里发明了功能,为什么不发疯呢。
这种存储方法也相当危险,因为 table 和列名完全可以更改,但希望这至少概述了我正在考虑的那种行为。
6NF中的一个table有一个CK(候选键)(在SQL中是一个PK)并且最多有一个其他列。本质上,6NF 允许每个 pre-6NF table 的列的更新 time/version 和以无异常方式记录的值。您通过删除非主列同时添加 table 和旧 CK 的列来分解 table。对于 temporal/versioning 应用程序,您进一步添加一个 time/version 列,新的 CK 是旧的加上它。
向 CK 添加一列 time/whatever 间隔(在 SQL 开始时间和结束时间列中)而不是时间允许通过记录最长的不间断时间段或其他时间来进行一种数据压缩列具有相同值的维度。一个查询由原始 CK 加上您想要其值的时间。你不需要这个用于你的目的,但是标准化到 6NF 的初始过程和添加 time/whatever 列应该在临时教程中解释。
阅读有关 temporal databases(它处理 "valid" 时间和时间间隔的数据以及 "transaction" times/versions 数据库更新)和 6NF 及其作用在他们中。 (Snodgrass/TSQL2 不好,Date/Darwen/Lorentzos 好,SQL 有问题。)
您最终建议的 table 是 EAV 的示例。这通常是一种反模式。它将数据库编码为一个或多个 table 有效元数据。但是由于 DBMS 不知道您失去了它的大部分功能。如果 DDL 足以管理包含您需要的列的 table,则不需要 EAV。只需在每个数据库中声明适当的 tables。这实际上是一个数据库,因为您希望交易会影响两者。从那个 link:
You are using a DBMS anti-pattern EAV. You are (trying to) build part of a DBMS into your program + database. The DBMS already exists to manage data and metadata. Use it.
Do not have a class/table of metatdata. Just have attributes of movies be fields/columns of Movies.
The notion that one needs to use EAV "so every entity type can be extended with custom fields" is mistaken. Just implement via calls that update metadata tables sometimes instead of just updating regular tables: DDL instead of DML.