数据库设计为每个客户订单存储不同的产品

时间:2011-12-14 10:08:01

标签: mysql sql django

我正在构建一种将客户订单插入数据库的简单方法。 我们有几种产品,每种产品都需要不同的属性。

我开始设计以下表格:

CUSTOMER -> Order (FK to CUSTOMER) -> OrderItem (FK to Order)

现在我在想如何将特定于产品的表链接到 OrderItem 。 假设我有两个产品: product1(room_name,width,height,color)和product2(number,width,height,type,optionals)。我创建了两个不同的表并将它们与 OrderItem 链接起来,以获取特定选项,我错了吗? (当然会有不止两种产品)

我该怎么做?

4 个答案:

答案 0 :(得分:2)

以下是一些选项

  1. 恕我直言,我会选择一种继承模式,即一个名为“ProductBase”的新表,其中包含一个唯一的Surrogate。产品库将具有分类,例如“ProductType”,然后允许您加入相应的“子类”Product表。 OrderItem只引用代理。参照完整性是可执行的,它提供了扩展到其他形式的产品的机会。但是,它确实需要在所有Product表类型中使用通用的唯一代理。如果有其他表(OrderItem除外)引用Product,它也可以避免使用FK来复合键。

  2. OrderItem中的可空外键,即OrderItem对两种(所有)类型的产品表都具有可空的FK,尽管每行中只有一个存在。 通过将OrderItem内部连接到相应的Product表,可以消除基于NULL的“错误”产品连接。 RI仍然可以执行。

  3. 如果您在所有Product子类表上都有SAME类型的主键,那么您还可以在OrderItem上添加单个Product“Foreign”键和“ProductType”“Switch”。这里的问题是你不能强制执行RI。

  4. 那就是说,我真的不会为每一件产品创建一个新的表 - 当然有一些广泛的“类别”的产品可以统一的方式建模。

    毫无疑问,如果您出售飞机和杂货,您可能需要 AircraftProduct GroceryProduct ,但肯定是 A300 波音747 Cessna Skyhawk 将适合 AircraftProduct 中的行,即使每个表中有一些“可选”可空字段不适用于所有产品这个'类别'?

    编辑:首先查看Dems和Duffmo的帖子,看看是否可以通过使用EAV / Multivalue / Metadata模式对产品进行建模来避免要求拥有多个Product表。

答案 1 :(得分:1)

我有一个Product表,OrderItemProduct之间存在一对多关系。在FOREIGN KEY表格中放置OrderItem,指向其关联的Product

像你这样的设计意味着每次有新产品时你都必须添加一个表。那不行。您想通过插入新行来添加产品。

答案 2 :(得分:1)

没有办法可以解决您可能遇到的所有问题,您所做的选择取决于哪个因素对您最重要。


大多数人都避免拥有多张桌子。一个原因是你不知道将来可能会有多少桌子。另一个原因是你的查询也可能因为必须加入多个表而膨胀。每次添加表时,多次查询都会更新,这可能会让您感到头疼。最后,添加一个表甚至不像添加记录那样友好(你真的希望你的应用程序能够创建表吗?)。


一个选项就是向Product表添加越来越多的字段。通过使属性字段为NULLable,不同的产品可以使用不同的字段。

但是......您可能需要添加逻辑以确保ProductX -always-在FieldA中具有值,但是ProductY总是在FieldB中具有值等等。并且可能是关于每种产品类型的一些元数据所以您的应用程序知道哪些产品用于哪些产品。您仍然可能需要添加新字段,这可能比添加新表更整洁,但您可能仍然不希望应用程序正在执行。


完全避免使用DDL添加产品的选项是进一步规范化数据,并在Entity-Attribute-Value表中具有特定于产品的属性。这对最初非常有吸引力,因为它非常通用和灵活。

  • 产品(id,name,another-global-property等)
  • Product_Properties(product_id,property_id,property_value)

您可能会有一些元数据和额外的逻辑来确保使用所有正确的属性。但现在您只需在创建新产品时将记录添加到通用结构中。

但“物业价值”应该是什么类型?它可能需要保存字符串,日期,数字,任何东西。您可以将其设为字符串并使用元数据来了解如何对值进行CAST。你们可能有几个值字段,每种类型中的一个,以及“field_type_id”或者用于指示应该从哪个值字段读取的东西。

某些搜索也不太友好。如果您知道product_id,则很容易找到属性。如果您想要所有过期日期的产品,您需要注意如何构建数据和索引以使查询有效。但是如果你想要(到期时间<今天和费用> 50)那么你会得到一个与你习惯的不同的查询 - 每个值都在不同的ROW而不是不同的FIELD。

随着查询复杂性的增加和设计考虑变得更加技术化,搜索性能确实开始缩小。


你走哪条路取决于应用功能要求,架构和设计决策,以及良好的“品味”。

答案 3 :(得分:1)

您已将标记为django的问题。那么你应该阅读这篇最近的帖子:

Coding an inventory system, with polymorphic items and manageable item types

在这篇文章中@ThibaultJ解释了如何使用Django model utils完成此任务。

您的想法是拥有“产品”模型,并从此模型继承product1和product2,为两者添加特定信息。 @ThibaultJ发布了样本。

我会注意到@ThibaultJ关于这个问题。如果@ThibaultJ写了一个答案,我将删除我的帖子。