【问题标题】:Basic mysql versioning?基本的mysql版本控制?
【发布时间】:2012-11-01 21:42:51
【问题描述】:

我们有一个如下图所示的购物车,该设置运行良好,除了一个致命缺陷。如果您下订单,则订单与产品相关联,因此如果我在您购买产品后更新产品,我无法向您展示您想要产品在您购买时的样子(包括价格)。这意味着我们需要版本控制。

我目前的计划是,当创建新产品或变体或编辑现有产品时,在数据库中创建产品或变体的副本。购买时,将订单链接到版本,而不是产品。

这看起来相当简单,除了我可以看到我们唯一不需要版本化的是类别(因为没有人关心它属于什么类别。)。所以我们需要版本:

  • 产品
  • 变体
  • 每个版本的键 -> 值对属性
  • 图片

我现在的想法是,

注意: 当一个产品被创建时,一个默认的变体也会被创建,这不能被移除。

  • 创建产品时
    • 将产品插入产品表中。
    • 创建默认变体
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加 id 列
    • 将变体复制到 variant_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加 id 列
      • 将 product_id 列替换为 product_version_id 列

  • 编辑产品时
    • 将产品更新到产品表中。
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加 id 列
    • 将所有产品变体复制到 variant_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加 id 列
      • 将 product_id 列替换为 product_version_id 列
    • 将所有 variant_image_links 复制到 variant_Image_link_version 表中
      • 用 variant_version_id 列替换当前的 variant_id 列

  • 添加变体时
    • 将变体添加到变体表中。
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加 id 列
    • 将所有产品变体复制到 variant_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加 id 列
      • 将 product_id 列替换为 product_version_id 列

  • 编辑变体时
    • 更新变体表中的变体。
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加 id 列
    • 将所有产品变体复制到 variant_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加 id 列
      • 将 product_id 列替换为 product_version_id 列
    • 将所有 variant_image_links 复制到 variant_Image_link_version 表中
      • 用 variant_version_id 列替换当前的 variant_id 列

所以最终的结构看起来像Full Size

现在这一切看起来都很棒,除了看起来有很多重复的数据,例如如果我们更新产品,我们会复制变体,即使它们在插入后不会更新。此外,这似乎需要大量工作。

有更好的方法吗?

【问题讨论】:

  • 你用什么程序来绘制这些图表?我喜欢它的外观。
  • +1 获取 dbdsgnr.appspot.com 信息,+1 获取问题。我很惊讶这在“标准数据库模型”一书中没有涉及。如果有,我想知道是哪一个。不记得另一本书是针对不同行业领域的大量已知/所需模型的集合。
  • 这本书我指的是:The Data Model Resource Book - Len Silverston。但它不包括通用数据版本控制

标签: mysql database database-design versioning database-versioning


【解决方案1】:

您可以执行 ERP(也可能是工资单)系统所做的事情:添加开始和结束日期/时间。所以...

  • 变体和价格根据共同日期与其产品相匹配。
  • 所有查询默认在当前日期运行,每个表之间的连接还需要考虑重叠/相交的日期范围。 parent_start_date <= child_start_date AND parent_end_date >= child_end_date
  • 您最终会为每个价格变化或变体保留重复的行,但是当产品价格发生变化时,您不需要保持更新尽可能多的记录(如变体 ID)。
  • 需要确保使用有效日期。 PS:使用系统的最大日期作为最新/最近记录的结束日期时间。

顺便说一句,一些相关的问题:

【讨论】:

  • 这听起来是个好主意,所以让我们看看我是否可以在下面的 cmets 中分解它,如果有任何问题,请告诉我。
  • New Product Created 将产品添加到 products 表中,填写开始日期,结束日期为空,与变量表中的默认变量相同。跨度>
  • Product Edited UPDATE products SET end_date = NOW() WHERE id={id} AND end_date IS NULL 插入新产品,end_date 为空。
  • 已编辑变体 UPDATE products SET end_date = NOW() WHERE id={id} AND end_date IS NULL UPDATE variants SET end_date = NOW() WHERE id={id} AND end_date IS NULL 将已编辑的变体插入为新行,设置开始日期并将结束日期留空,插入重复产品,设置开始日期
  • 添加变体 UPDATE products SET end_date = NOW() WHERE id={id} AND end_date IS NULL 插入新变体作为新行。插入重复的产品设置 start_date
【解决方案2】:

另一种方法是永远不要编辑或删除您的数据,只创建新数据。在 SQL 术语中,您曾经对表运行的唯一操作是 INSERT 和 SELECT。

要完成您想要的,每个表都需要以下列:

  • version_id - 这将是您的主键
  • id - 这就是将对象的各个版本保存在一起的东西(例如,要查找产品的所有版本,SELECT * FROM products WHERE id = ?)
  • 创作日期
  • is_active - 您没有删除任何内容,因此您需要标记以(逻辑上)删除数据

这样,您的产品表将如下所示:

CREATE TABLE products (
  version_id CHAR(8) NOT NULL PRIMARY KEY,
  id INTEGER NOT NULL,
  creation_date TIMESTAMP NOT NULL DEFAULT NOW(),
  is_active BOOLEAN DEFAULT true,
  name VARCHAR(1024) NOT NULL,
  price INTEGER NOT NULL
);

CREATE TABLE variants (
  version_id CHAR(8) NOT NULL PRIMARY KEY,
  id INTEGER NOT NULL,
  creation_date TIMESTAMP NOT NULL DEFAULT NOW(),
  is_active BOOLEAN DEFAULT true,
  product_version_id CHAR(8) NOT NULL,
  price INTEGER NOT NULL,
  override_price INTEGER NOT NULL,
  FOREIGN KEY (product_version_id) REFERENCES products(version_id)
);

现在,插入任一表

  1. 生成唯一的 version_id(有几种策略,一种是使用数据库序列,或者对于 MySQL 使用 ant AUTO_INCREMENT)。
  2. 生成一个 ID。此 ID 对于产品的所有版本都是一致的。

要更新表格中的一行,必须插入整个图表,例如要更新产品,必须插入新产品和新变体。 (这里有很大的优化空间,但最容易从未优化的解决方案开始。)

例如,更新产品

  1. 生成唯一的 version_id
  2. 使用相同的ID
  3. 插入新产品变体。变体将与链接到您正在“更新”的产品的先前版本的变体相同,只是 product_version_id 不同。

此主体可以扩展到您的所有表。

要查找产品的最新版本,您需要使用 creation_date 列来获取最近创建的产品。

此模型将使用更多空间,但我认为这可能是一个公平的权衡,因为它很简单:只有 INSERT 和 SELECT,并且数据永远不会发生变化。

【讨论】:

  • 这不是类似于draw-pierce的答案吗?此外,在您的示例中,数据仍然会发生变异,因为您仍然需要更新 is_active 字段。老实说,我认为这种方法没有任何问题,有时带有 is_active 标志 + version_number 的“creation_date”更容易追踪。
  • 是的,类似,但又不一样。我的解决方案没有更新。数据没有变异。为什么你认为 is_active 字段需要改变?
  • 明确地说,is_active 字段旨在允许从目录中逻辑删除产品。可以添加另一个字段 is_this_the_most_recent_version。该字段将被突变。也许这就是混乱所在?
  • 是的,我对那部分感到困惑。但是在你的模型中,is_this_the_most_recent_version 不应该是必需的 - 最大 id 或创建日期就足够了。
  • 正确,is_this_the_most_recent_version 是不必要的优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-15
  • 2015-03-10
  • 2010-12-27
  • 1970-01-01
  • 2010-10-01
  • 2010-12-19
  • 1970-01-01
相关资源
最近更新 更多