13

我试图弄清楚如何设计我的数据库表以允许撤消重做。

假设您有一个具有以下结构的任务表:

id <int>
title <varchar>
memo <string>
date_added <datetime>
date_due <datetime>

现在假设在几天内多次登录并进行了多次编辑;但用户想回到其中一个版本。

  1. 您是否有一个单独的表来跟踪更改 - 或者 - 您是否会尝试将更改保留在任务表中(“幽灵”行,因为没有更好的术语)?
  2. 您会跟踪所有列还是只跟踪每次更改的列?

如果重要的话,我正在使用 MySQL。另外,如果重要的话,我希望能够显示历史记录(ala Photoshop)并允许用户切换到任何版本。

额外问题:您会在更改时保存整个memo单元格还是尝试仅保存增量?我问的原因是因为memo单元格可能很大,每次修订只能更改一个单词或字符。诚然,保存增量需要解析,但如果不经常期望撤消,那么节省空间而不是处理时间不是更好吗?

感谢您的帮助。

4

3 回答 3

8

我会为您的任务表创建一个历史记录表。与任务相同的结构 + 一个名为 previousId 的新字段。这将保存先前的更改 ID,因此您可以通过不同的更改(撤消/重做)来回返回。

为什么是新的历史表?原因很简单:不要让任务表中的东西不适合它。

至于空间,在历史记录中,而不是备忘录,使用二进制格式并压缩要存储的文本内容。不要试图检测变化。你会遇到一个错误的代码,这会导致沮丧和浪费时间......

优化:更好的是,您可以在 History 表中只保留三列:1. taskId(任务的外键) 2. data - 一个二进制字段。在历史表中保存之前,创建一个 XML 字符串,其中仅包含已更改的字段。3. previousId(将有助于维护更改队列并允许来回导航)

对于数据字段,创建一个 XML 字符串,如下所示:

<task>
  <title>Title was changed</title>
  <date_added>2011-03-26 01:29:22<date_added>
</task>

这基本上会告诉您,这次您只更改了 title 和 date_added 字段。

构建 XML 字符串后,如果需要,只需将其压缩并将其存储到历史表的数据字段中。

XML 也将允许灵活性。如果您在任务表中添加/删除字段,您也不需要更新历史表。所以这种方式任务表和历史表的结构是解耦的,所以你不需要每次更新两个表。

PS:不要忘记添加一些索引以快速浏览历史表。要索引的字段:taskId 和 previousId,因为您需要针对此表进行快速查询。

希望这可以帮助。

于 2011-03-26T00:56:45.577 回答
3

当我使用 SQL 做类似类型的事情时,我总是使用第二个表来记录修订历史。这可以防止您的主表在版本中变得过大。理由是检索当前记录几乎 100% 发生,查看历史记录和回滚(撤消)非常罕见。

如果您只有一个 UNDO 或历史记录,那么在表中跟踪可能就可以了。

您是要保存增量还是整个单元格取决于预期的增长/使用情况。如果您愿意创建管理增量的逻辑,那将节省您的空间。如果事情没有真正创造出我通常不会开始的新版本,(应用 YAGNI)

于 2011-03-26T00:36:22.110 回答
3

您可能希望以 delta 形式压缩修订,但您仍应拥有完整的当前修订以便快速检索。

但是,从旧到新的增量需要大量处理,除非您有一些非增量可作为基础。每次发生变化时,较新到较旧的增量都需要重新处理。因此,增量通常不会为您带来很多好处,但会带来更大的复杂性。

上次我检查,那是几年前, Wikipedia 背后的软件MediaWiki存储了全文,并提供了一些方法来使用 gzip 压缩旧修订以节省空间,并archive为已删除的修订/页面提供了一个专用表。

他们的网站有一个他们的数据库布局的 ER 图,您可能会发现它很有用。

于 2011-03-26T00:53:09.490 回答