【问题标题】:How to handle an immutable table referencing mutable tables?如何处理引用可变表的不可变表?
【发布时间】:2009-08-25 00:57:53
【问题描述】:

在.NET 中创建一个非常标准的在线商店时,我遇到了一些关于我的数据库的架构难题。我有一个表“Orders”,由表“OrderItems”引用。后者引用了一个表“产品”。
现在,orders 和 orderitems 表在大多数方面是不可变的,也就是说,无论您在查看表时,创建的订单及其 orderitems 看起来都应该相同(例如,每年打印一份用于记账的订单的收据应产生与客户在订单时收到的相同收据)。
我可以想到两种实现这种行为的方法,其中一种现在正在使用:
1. 非规范化,将产品价格等值复制到 orderitem 表中。
2. 使引用表不可变。每当价格等值发生变化时,处理产品的代码就可以创建一个新产品。引用产品的可变表会更新它们的引用,而不可变的表会很好地使用它们的旧引用

您首选的方法是什么?有没有更好、更聪明的方法来做到这一点?

【问题讨论】:

    标签: database database-design


    【解决方案1】:

    这取决于。我正在写一个相当复杂的企业软件,其中包括一种文档管理和审计,并用于药房。

    通常,原始值是非规范化的。例如,如果您只需要创建订单时客户的当前状态,我会将其存储到订单中。

    几乎每个时间点都需要提供更复杂的数据。有两种方法:创建它们的历史记录,或者实施修订控制系统,这几乎是相同的。

    历史意味着曾经存在的每个状态都作为单独的记录存储在同一个或另一个表中。

    我实施了一个修订控制系统,我将记录分成两个表,一个用于实际项目,比如产品,另一个用于其版本。这样我就可以引用整个产品或它的任何特定版本,因为它们都有自己的主键。

    该系统用于许多实体。我可以安全地从审计跟踪或其他不可变记录中引用受修订控制的对象。一开始这样的系统似乎比较复杂,但到最后它非常简单,一次解决了很多问题。

    【讨论】:

      【解决方案2】:

      如果价格会随时间变化,那么将价格同时存储在 Product 表和 OrderItem 表中并不是非规范化的。规范化规则说每个“事实”应该在数据库中只记录一次。但在这种情况下,仅仅因为这两个数字都被称为“价格”并不能使它们成为同一件事。一个是当前价格,另一个是截至销售日期的价格。这些是非常不同的事情。就像“客户邮政编码”和“商店邮政编码”是完全不同的字段一样;两者都可能简称为“邮政编码”这一事实并不能使它们成为同一件事。就个人而言,我强烈反对将包含不同数据的字段命名为相同的名称,因为这会造成混淆。我不会同时称它们为“Price”:我会称一个为“Current_Price”,另一个为“Sale_Price”或类似的名称。

      在销售时不保持价格显然是错误的。如果我们需要知道这一点——我们几乎肯定会这样做——那么我们需要保存它。

      每次销售或每次价格变化时都复制整个产品记录也是错误的。您几乎可以肯定拥有关于产品的恒定数据,例如描述和供应商,这些数据不会在每次价格变化时都发生变化。如果您复制产品​​记录,您将复制所有这些数据,这肯定是非规范化。这会产生许多潜在的问题。就像,如果有人修复了产品描述中的拼写错误,我们现在可能会有新记录说“4-slice toaster”,而旧记录说“4-slice taster”。如果我们生成报告并对描述进行排序,它们将被分开并看起来像不同的产品。等等。

      如果您关心的关于产品的唯一变化数据是价格,那么我只需将价格发布到 OrderItem 记录中即可。

      如果有大量数据发生变化,那么您希望将 Product 表分成两个表:一个用于不变的数据或您不关心其历史的数据,另一个用于需要跟踪的数据历史。比如,有一个 ProductBase 表,其中包含描述、供应商、库存编号、运输重量等;以及一个 ProductMutable 表,其中包含我们的成本、销售价格以及任何其他经常变化的内容。您可能还想要一个截止日期,或者至少是一个最新的指示。 ProductMutable 的主键可以是 Product_id 加上 As_of_date,或者如果您更喜欢所有表的简单顺序键,很好,它至少有对 product_id 的引用。 OrderItem 表引用 ProductMutable,而不是 ProductBase。我们通过 ProductMutable 找到 ProductBase。

      【讨论】:

        【解决方案3】:

        我认为非规范化是要走的路。

        此外,产品不应该有价格(当它不时变化以及价格对不同的人意味着不同的价值时 -> 零售商、客户、大宗卖家等)。

        您还可以有一个价格历史记录表,其中包含 ProductID、FromDate、ToDate、Price、IsActive - 以维护产品的价格历史记录。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-12
          • 1970-01-01
          • 2013-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-05
          相关资源
          最近更新 更多