Nic*_*ckH 0 mysql sql database-design foreign-keys
我的旅行项目架构的一部分有以下表格
Cruises
Flights
Hotels
CarParking
Run Code Online (Sandbox Code Playgroud)
我需要一个容器,将一个或多个这些产品包装成一个包装.一个游轮/酒店等可能是许多套餐的一部分.我最初想到的
Package
- PackageId
- Etc
PackageItem
- PackageItemId
- PackageId (fk)
- ItemId (fk)
- ItemType
Run Code Online (Sandbox Code Playgroud)
其中ItemType表示它是Cruise,Flight,Hotel等.我想我可以使用Triggers来强制引用完整性.
我的另一个想法是
Package
- ...
PackageItem
- PackageItemId
- PackageId (fk)
- CruiseId (nullable fk)
- FlightId (nullable fk)
- HotelId (nullable fk)
- CarParkingId (nullable fk)
- etc
Run Code Online (Sandbox Code Playgroud)
我想每个人都有利有弊,但我无法决定.你觉得哪个更好,如果你必须实现这样的话,你会选择哪个?
数据库是MySql.平台是C#MVC ASP.NET
(我做了搜索,但也有一些相似的问题,但没有任何相应的问题)
第一种选择是最灵活的.而且我倾向于灵活性.
优点:常见查询
如果您想要有关巡航的报告,则查询与酒店的查询相同,但具有不同的WHERE子句.
使用第二种形式,您需要加入并从不同的表中进行选择.
*优势:没有架构变化的增长
如果您需要将Excursions添加到模型中(当然可以将许多内容与单个包关联),您只需创建一个新的Excursions类型.
使用第二种形式,您需要向表中添加新字段,创建新表以保存数据,以及更新查询和逻辑以使用这些新表和字段.
成本:数据转移到对人类消化不友好的形式
许多人可以合理地说这根本不重要.我说这很重要,因为你必须考虑到它...
- 它可以使调试更加困难,所以你需要更加规范和有条不紊
- 这意味着你的GUI必须更聪明地转换你的数据用于显示
此外,虽然这是一个成本,但它有一个好处,就是强迫你进入一个不太可能的中间位置,因此做出简单的假设并犯下草率的错误.这是我喜欢的费用.
Falacy:不能强制执行约束
约束 - 每个包组件必须是酒店,包装,飞行或巡航
方法 - 有一个component_type表,并且FK到该表
约束 - 每个包只允许一种类型
方法 - 对(package_id,component_type_id)的UNIQUE约束
约束 - 每个组件只能在一个包中 - 对(component_id)的UNIQUE约束
成本 - 延迟复杂性
在我看来,将包映射到组件的规范化表实际上是简单而优雅的.下一步是确定如何存储组件的相关详细信息.
单个全局"组件"表可以包含所有字段,但允许它们可以为空.因此,HOTEL将具有NULL Flight_Number.但所有组件都有价格.
或者您可以创建Entity_Attribute_Value表.这可以通过这样的方式形成,以防止酒店有航班号......
- component_attributes table =(id,type_id,attribute_id,attribute_value)
- (type_id,attribute_id)可以外键控制到允许的组合
执行必需的字段(例如Price)是不可能的(afaik).
Value通常存储为VARCHAR.
出于这个原因,和其他人一样,通过Value搜索数据变得困难.
最终意见
我不会使用选项2,因为这是高度约束并将两个考虑因素合并在一起 - 如何保存不同组件类型(酒店,航班等)的数据以及如何将它们与其父包相关联.
我建议您考虑保存组件数据的多种方法,并根据您的需要做出决定.然后使用1:多标准化映射表将这些组件与包关联.你的选择1.