我想在即将到来的Web应用程序中实现一些登台/版本转换功能。

尽管我在下面提到了MySQL / Doctrine和MongoDB / Mongoose标签,但实际上我并不局限于其中之一。这些只是我通常使用的。我将选择最合适的技术。

基本上,我想允许我的用户还原更改,保存草稿(分支),发布更改(合并/提交)等等。就像git在代码中所做的一样,我希望这种行为用于数据。

我知道这种行为在很大程度上取决于应用程序代码,但是首先我需要找到合适的数据库模式。

尽管使用简单的表并不难,但是当具有多个关系的表时,我很难找到一个好的/干净的解决方案。我能想到的每种方法都会产生大量的冗余数据,或者看起来太复杂了。

想象以下数据,其中每个帖子可以有多个标签:

-- Create syntax for TABLE 'post'
CREATE TABLE `post` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`),
  KEY `name` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Create syntax for TABLE 'post_tag'
CREATE TABLE `post_tag` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `post_id` int(11) DEFAULT NULL,
  `tag_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Create syntax for TABLE 'tag'
CREATE TABLE `tag` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `label` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


每次更改都复制整个post和post_tag表是不对的。特别是因为我最后将得到另外5个相关的表。

当与包含二进制数据或大字符串的表建立OneToMany关系时,情况甚至更糟。在每次更改时无缘无故地复制它们会导致大量无用的数据。

但是也许这是要走的路?

最佳答案

当然,您的post具有多个id? (如果是这样,请编辑以添加省略号或其他内容。)

Tag表。从idpost_tag并将tag_id替换为label。这是一个将“标签”添加到“帖子”的好模式:

CREATE TABLE `post_tag` (
  `post_id` int(11) NOT NULL,
  `tag` varchar(64) NOT NULL,
  PRIMARY KEY (post_id, label),  -- also prevents duplicate entries
  INDEX(tag, post_id)            -- for going the other way
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Rick's RoTs之一:“规范化,但不要过度规范化”。其他一些:适当时使用UNSIGNED和/或NOT NULL

以上仅涉及“标记”。如果您要讨论版本控制,请将其分开作为一个单独的问题。将两个不相关的问题放在一起是不好的。 (当然,“标记”可能是“版本控制”的工具,但我认为不是。)

关于mysql - 如何在数据库中存储可版本化的数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43588359/

10-10 17:18
查看更多