mysql - 如何设计具有撤消重做功能的 SQL 数据库?

标签 mysql sql undo-redo delta audit-tables

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

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

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

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

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

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

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

感谢您的帮助。

最佳答案

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

为什么要使用新的历史记录表?原因很简单:不要让 tasks 表中的东西不适合它。

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

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

对于数据字段,创建一个这样的 XML 字符串:

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

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

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

XML 也将允许灵 active 。如果您在任务表中添加/删除字段,您也不需要更新历史表。这样一来,tasks 表和 History 表的结构就解耦了,不需要每次都更新两个表。

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

希望这会有所帮助。

关于mysql - 如何设计具有撤消重做功能的 SQL 数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5439501/

相关文章:

php - 如何使用选择框从数据库行 symfony2 中获取数据

Mysql Date 在 where 子句中?

mysql - 关于MySQL数据库迁移的问题

mysql - 如何导出 sugarcrm 中的潜在客户历史记录部分?

php - 检索与输入的用户名匹配的所有用户的最后一条消息

mysql - SQL 选择最常见的值

java - 在JOOQ中将RDS数据写入磁盘

c++ - Qt Undo Framework下显式调用redo()

javascript - 如何在 kineticjs 中创建撤消-重做?