10

我有一个 CMS 系统,可以跨表存储数据,如下所示:

Entries Table
+----+-------+------+--------+--------+
| id | title | text | index1 | index2 |
+----+-------+------+--------+--------+

Entries META Table
+----+----------+-------+-------+
| id | entry_id | value | param |
+----+----------+-------+-------+

Files Table
+----+----------+----------+
| id | entry_id | filename |
+----+----------+----------+

Entries-to-Tags Table
+----+----------+--------+
| id | entry_id | tag_id |
+----+----------+--------+

Tags Table
+----+-----+
| id | tag |
+----+-----+

我正在尝试实施一个修订系统,有点像 SO。如果我只是为了这样做,Entries Table我打算将对该表的所有更改的副本保存在一个单独的表中。因为我必须为至少 4 个表执行此操作(TAGS 表不需要修改),所以这似乎根本不是一个优雅的解决方案。

你们会怎么做呢?

请注意,元表是在EAV (entity-attribute-value)中建模的。

先感谢您。

4

3 回答 3

8

嗨,目前正在研究类似问题的解决方案,我正在通过将我的表分成两个表来解决它,一个控制表和一个数据表。控制表将包含一个主键和对数据表的引用,数据表将包含自增修订键和控制表的主键作为外键。

以您的条目表为例

Entries Table
+----+-------+------+--------+--------+
| id | title | text | index1 | index2 |
+----+-------+------+--------+--------+

变成

entries             entries_data
+----+----------+   +----------+----+--------+------+--------+--------+
| id | revision |   | revision | id |  title | text | index1 | index2 |
+----+----------+   +----------+----+--------+------+--------+--------+

查询

select * from entries join entries_data on entries.revision = entries_data.revision;

您使用 insert 语句而不是更新 entries_data 表,然后使用条目表的新修订版更新条目表的修订版。

该系统的优点是您可以通过更改条目表中的修订属性来移动到不同的修订。缺点是您需要更新查询。我目前正在将其集成到 ORM 层中,因此开发人员无论如何都不必担心编写 SQL。我正在玩弄的另一个想法是有一个所有数据表都使用的集中修订表。这将允许您使用单个修订号来描述数据库的状态,类似于颠覆修订号的工作方式。

于 2010-08-17T23:09:35.510 回答
6

看看这个问题:How to version control a record in a database

为什么不为每个表设置一个单独的 history_table (根据链接问题的公认答案)?这只是具有原始表的 PK 和修订号的复合主键。毕竟,您仍然需要将数据存储在某个地方。

于 2010-08-14T05:22:18.173 回答
1

对于我们的一个项目,我们采用了以下方式:

Entries Table
+----+-----------+---------+
| id | date_from | date_to |
+----+--------_--+---------+

EntryProperties Table
+----------+-----------+-------+------+--------+--------+
| entry_id | date_from | title | text | index1 | index2 |
+----------+-----------+-------+------+--------+--------+

相当复杂,仍然允许跟踪整个对象的生命周期。因此,对于查询我们想要的活动实体:

SELECT 
entry_id, title, text, index1, index2
FROM
Entities INNER JOIN EntityProperties
ON Entities.id = EntityProperties.entity_id
AND Entities.date_to IS NULL
AND EntityProperties.date_to IS NULL

唯一担心的是实体被删除(所以我们在那里放了一个 date_to)然后由管理员恢复的情况。使用给定的方案没有办法跟踪这种技巧。

任何这样的尝试的总体缺点是显而易见的——你必须编写大量的 TSQL,其中非版本控制的数据库将用于诸如select A join B 之类的东西。

于 2010-08-26T06:08:27.180 回答