版本控制很简单,例如page
的条目有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”。
但是,如何跟踪可能与条目具有一对多关系的相关值的版本?例如如果通过添加category
和category_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;
如果用户在页面中添加了新类别(“2”),如何捕获更改(在foo
更改为Foo
时的相同更改)?
答案 0 :(得分:0)
如果要在同一位置跟踪版本(比如相同的entry_timestamp字段),可以使用page_category表上的触发器实现该版本。 查看更多here,该页面底部有一个示例。
答案 1 :(得分:0)
您使用术语“版本”但是,正如jeremycole所评论的那样,您不清楚原因是否需要它。
如果只是提供数据随时间变化的历史记录,那么数据库中每个表的附加表就足够了;看来这就是您在page_version
表格中已有的内容。
这些历史记录表将允许您在某个时间点从数据库中检索“对象”的状态,这就是我使用术语“历史记录”的原因。将其称为版本意味着将数字或其他标识符应用于定义“对象”的数据集合。您似乎没有在表结构中使用它。
从一个时间点重建关系数据将涉及编写加入适当表的常规查询,但在您感兴趣的时间点或之前添加匹配数据行。虽然这可以完成后,当连接中的表数增加时,它变得难以处理。
另一种方法是在应用程序中创建对象的一个版本并将其存储在数据库中。例如,使用XML或JSON对对象进行编码,并将整个事物(作为字符串)与版本号和日期戳一起放在表中。
这使得在给定版本号的情况下检索整个对象变得容易,尽管它需要应用程序在再次将数据写入数据库之前从XML / JSON数据构造内存中对象(如果您想要的话)恢复到以前的版本)。这应该不会太难,因为您已经在读取/写入关系表的对象,您只需要添加对象流代码。
在不了解存储历史/版本的原因的情况下,很难推荐一种方法而不是另一种方法。我使用由触发器管理的简单历史表来记录系统中数据的更改,但是我们没有要求“回滚”到以前的版本。我们使用历史记录进行奇怪的场合,我们需要撤消单个编辑,并通过记录进行更改的人的用户名作为“责备”路径:)
我建议您阅读Richard Snodgrass撰写的Developing Time-Oriented Database Applications in SQL(PDF链接位于“图书”部分的第一段)。这不是一本简短的书,但它对我帮助很大。