2

版本控制很简单,使用诸如pagehas之类的条目name。无论是使用触发器还是应用程序逻辑,我都会有一个表page_version来存储每次更新时行的每个先前值。page

CREATE TABLE `page` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `page` (`id`, `name`)
VALUES
    (1,'Foo');

CREATE TABLE `page_version` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `page_id` int(10) unsigned NOT NULL,
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `entry_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `page_id` (`page_id`),
  CONSTRAINT `page_version_ibfk_1` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `page_version` (`id`, `page_id`, `name`, `entry_timestamp`)
VALUES
    (1,1,'foo','2013-09-19 20:27:06');

在这个例子中,我知道它page.name从“foo”变成了“Foo”。如果再次更改(例如,更改为“Bar”),则将添加“Foo”值并将page_version原始行page.name更新为“Bar”。

但是,如何跟踪可能与条目具有一对多关系的依赖值的版本?例如,如果后一种模式通过添加categorycategory_page表来补充。

CREATE TABLE `category` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `category` (`id`, `name`)
VALUES
    (1,'One'),
    (2,'Two');

CREATE TABLE `page_category` (
  `page_id` int(10) unsigned NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`page_id`,`category_id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `page_category_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE,
  CONSTRAINT `page_category_ibfk_1` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

如果用户向页面添加了新类别(“Two”),如何捕获更改(更改为时的相同更改foo) ?Foo

4

2 回答 2

0

如果您想在同一个地方跟踪版本(比如相同的 entry_timestamp 字段),您可以使用 page_category 表上的触发器来实现。在此处查看更多信息,该页面底部有一个示例。

于 2013-09-24T08:36:35.410 回答
0

您使用“版本”一词,但正如 jeremycole 评论的那样,您不清楚需要它的原因

如果只是提供数据随时间变化的历史记录,那么为数据库中的每个表添加一个表就足够了;看来这是您的page_version桌子已经拥有的东西。

这些历史表将允许您在某个时间点从数据库中检索“对象”的状态,这就是我使用“历史”一词的原因。将其称为版本意味着有数字或其他标识符应用于定义“对象”的数据集合。您的表结构中似乎没有这个。

从某个时间点重建关系数据将涉及编写连接适当表的正常查询,但需要在您感兴趣的时间点或之前匹配数据行。虽然可以这样做,当连接中的表数量增加时,它变得笨拙。

另一种方法是在应用程序中创建对象的一个​​版本并将其存储在数据库中。例如,使用 XML 或 JSON 对您的对象进行编码,并将整个事物作为字符串连同版本号和日期戳一起放入表格中。

这使得在给定版本号的情况下检索整个对象变得很容易,尽管它需要应用程序从 XML/JSON 数据构造内存中的对象,然后才能再次将其写入数据库(如果您想恢复到以前的版本)。这应该不会太难,因为您已经在向关系表读取/写入对象,您只需要添加对象流代码。

在不了解存储历史/版本的原因的情况下,很难推荐一种方法而不是另一种方法。我使用由触发器管理的简单历史表来记录系统中数据的更改,但是我们不需要“回滚”到以前的版本。我们将历史记录用于某人犯错的奇怪情况,我们需要撤消一次编辑,并通过记录进行更改的人的用户名作为“责备”线索:)

我建议您阅读Richard Snodgrass的用 SQL 开发面向时间的数据库应用程序(指向 PDF 的链接在“书籍”部分的第一段中)。这本书不短,但对我帮助很大。

于 2013-09-27T15:07:47.670 回答