【问题标题】:Best Way to Design These Tables设计这些表格的最佳方式
【发布时间】:2012-01-13 22:39:00
【问题描述】:

我的旅行项目架构的一部分包含以下表格

Cruises
Flights
Hotels
CarParking

我需要一个将这些产品中的一种或多种包装成一个包装的容器。一艘邮轮/酒店等可能是许多套餐的一部分。我一开始想到的

Package
- PackageId
- Etc

PackageItem
- PackageItemId
- PackageId (fk)
- ItemId (fk)
- ItemType

ItemType 将指示它是否是 Cruise、Flight、Hotel 等。我想我可以使用触发器来强制引用完整性。

我的另一个想法是

Package
- ...

PackageItem
- PackageItemId
- PackageId (fk)
- CruiseId (nullable fk)
- FlightId (nullable fk)
- HotelId (nullable fk)
- CarParkingId (nullable fk)
- etc

我想每个人都有优点和缺点,但我无法决定。你认为哪个更好,如果你必须实现这样的东西,你会选择哪个?

数据库是MySql。平台是 C# MVC ASP.NET

(我做了搜索,有几个类似的问题,但没有一个很好对应)

【问题讨论】:

    标签: mysql sql database-design foreign-keys


    【解决方案1】:

    第一个选项是最灵活的。而且我倾向于灵活选择。


    优势:常见查询

    如果您想要关于游轮的报告,查询与酒店查询相同,但 WHERE 子句不同。

    使用第二种形式,您需要加入并从不同的表中进行选择。


    *优势:无需更改架构即可实现增长

    如果您需要将 Excursions 添加到您的模型(可能肯定与单个包相关联的东西),您只需创建一个新的 Excursions 类型。

    使用第二种形式,您需要向表中添加新字段,创建新表来保存数据,并更新查询和逻辑以使用这些新表和字段。


    成本:数据迁移到不利于人类消化的形式

    许多人可以合理地说这根本不重要。我说,就您必须考虑到它而言,这很重要...
    - 它会使调试变得更加困难,因此您需要更加规范和有条理
    - 这意味着您的 GUI 必须更智能地转换数据以进行显示

    此外,虽然这是一种成本,但它的好处是迫使您进入不太可能的中间位置,因此做出简单的假设并犯下草率的错误。这是我喜欢的成本。


    谬误:无法强制执行约束

    约束 - 每个包裹组件必须是 Hotel、Packing、Flight 或 Cruise
    方法 - 有一个 component_type 表,以及该表的 FK

    约束 - 每个包只允许每种类型中的一种
    方法 - (package_id, component_type_id) 上的唯一约束

    约束 - 每个组件只能在一个包中 方法 - (component_id) 上的唯一约束


    成本 - 延迟复杂性

    在我看来,将包映射到组件的规范化表实际上是简单而优雅的。下一步是决定如何存储组件的相关细节。


    单个全局“组件”表可以保存所有字段,但允许它们为空。因此,HOTEL 将有一个 NULL Flight_Number。但所有组件都会有价格。


    或者您可以创建一个 Entity_Attribute_Value 表。这可以通过防止酒店拥有航班号的方式形成......
    - 组件属性表 =(id、type_id、attribute_id、attribute_value)
    - (type_id, attribute_id) 可以外键为允许的组合

    强制执行 REQUIRED 字段(例如价格)是不可能的(afaik)。
    该值通常存储为 VARCHAR。
    出于这个原因,以及其他原因,按价值搜索数据变得很困难。


    最终意见

    我会使用选项 2,因为它受到高度限制并将两个考虑因素合并在一起 - 如何保存不同组件类型(酒店、航班等)的数据以及如何将它们与他们的父包。

    我建议您考虑多种保存组件数据的方法,并根据您的需要做出决定。然后使用 1:many 规范化映射表将这些组件与包相关联。您的选择 1。

    【讨论】:

    • 感谢cmets和建议
    【解决方案2】:

    您没有提到是否需要在一个包中支持多个相同类型的产品 - 例如,包是否可以包含多个酒店。

    1) 如果需要每个包支持多个相同类型的产品,那么您应该采用第一种方式,但可能会根据产品类型将关系拆分为单独的表,即

    PackageHotelItem
    - PackageItemId
    - PackageId (fk)
    - HotelId (fk)
    
    PackageCruiseItem
    - PackageItemId
    - PackageId (fk)
    - CruiseId (fk)
    
    ... etc.
    

    这样,您将能够通过正常的 FK 机制获得参照完整性。

    2) 如果您不需要此类支持,那么您可以使用第二种解决方案。

    【讨论】:

    • 这将是我的选择,因为当新的包裹物品出现时,您最终不会得到包含大量字段的 PackageItem 表。
    • 感谢您的建议。一个包装中确实需要有多个相同类型的产品。我的两个选项都允许这样做,因为在这两种情况下,我都会有几个 PackageItems 组成一个包。
    • 您的第一个选项很有趣,但查询起来可能比我的第二个选项更复杂。要获得整个包,您必须查询每个 Package__Item 连接表,因此添加新产品类型会非常痛苦。
    • 是的,查询可能更复杂。但是你会得到清晰的数据库结构,如果你决定在某个时候添加,比如,RailwayStations,它也很容易扩展。一切都有其优点和缺点,包括我的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多