带/外键问题的数据库设计

时间:2009-11-13 23:28:38

标签: mysql database-design foreign-keys foreign-key-relationship

我正在尝试正确使用外键来维护数据完整性。我不是一个真正的数据库人,所以我想知道是否有一些我不知道的一般设计原则。以下是我正在尝试做的一个例子:

假设您要构建一个包含Type(汽车,卡车等),Make和Model的车辆数据库。用户必须至少输入Type,但Make和Model是可选的(如果给出Model,则需要Make)。我的第一个想法是建立数据库:

Type:
-id (PK)
-description

Make:
-id (PK)
-type_id (FK references Type:id)
-description

Model:
-id (PK)
-make_id (FK references Make:id)
-description

Vechicle:
-id (PK)
-type_id (FK references Type:id)
-make_id (FK references Make:id)
-model_id (FK references Model:id)

如何设置车辆的FK以确保Type,Make和Model都匹配?例如,你如何防止车辆(类型:摩托车,制造:福特,型号:思域)?其中每一个都是有效的FK,但它们不维持通过其他表的FK显示的关系。

另外,因为Model不是必需的,所以我不能只存储model_id FK并从中向后工作。

我根本不依赖于数据库设计,所以我很乐意不得不改变表的设置方式。有什么想法吗?

P.S。 - 如果有人感兴趣,我正在使用mysql,但这更像是关于数据库的一般性问题。

编辑(澄清):

车辆表中需要

-type_id和make_id,除非在model_id为空的情况下有某种方法可以解决这些问题;

- 需要维护type_id,make_id和model_id之间的关系。

5 个答案:

答案 0 :(得分:2)

像这样:

类型:

  • id(PK)
  • 描述

请:

  • id(PK)
  • type_id(FK引用类型:id,非null)
  • 描述

型号:

  • id(PK)
  • make_id(FK引用Make:id,not null)
  • 描述

运载工具:

  • id(PK)
  • model_id(FK参考模型:id)

基本上不要双重参考制造和车辆类型。如果你这样做,你会遇到问题。您可以从车辆模型中获取品牌和类型(如果已定义)。模特必须有。必须有类型。

考虑一下:如果车辆具有给定的车型,但车辆和车型都有车型,那么这些值可能会有所不同。由于信息冗余,这种不一致可能会发展。你想要避免这种情况。

如果您需要弄清楚车辆的品牌和类型,SQL开始如下所示:

SELECT v.id, v.model_id, m.make_id, k.type_id
FROM vehicle v
LEFT JOIN model m ON v.model_id = m.id
JOIN make k ON m.make_id = k.id
JOIN type t ON k.type_id = t.id

等等。

答案 1 :(得分:2)

您正在寻找的是CHECK约束。不幸的是,MySQL目前不支持此功能。您可以使用触发器模拟此类功能,但您需要创建INSERT和UPDATE触发器才能使其工作。

然而,正如其他答案所表明的那样,你真正应该存储的只是车型。在您的应用程序中,如果可用,您应该深入到该类型。

答案 2 :(得分:1)

这是一种方法:

- 一个制造(福特,通用,本田)可以有多个模型,一个模型只属于一个品牌。
- 型号属于某种(汽车,卡车自行车)。
- 车辆属于某种型号。一个车辆只能是一个车型;一个模型可以有很多车辆。

模型表包含所有模型共有的列;而汽车,卡车和摩托车都有专门针对每一个的列。

建模数据库时,请考虑数据,实体和关系;不要从用户界面开始 - 中间有一个业务层来排序。使用MySQL是可以的,您可以在应用程序层上强制执行检查和外键约束。

vehicle_model_01

答案 3 :(得分:0)

您的设计适用于数据完整性,应用程序的工作是保持车辆必须由特定品牌的特定类型和型号组成。

如果您想在数据库中维护车辆类型/品牌/型号的完整性,您可以在Vehicle表格中添加一个检查约束,以确保Vehicle的品牌类型ID等于提供的类型ID。如果模型id不为null,请确保它的make id与提供的make id相同。

答案 4 :(得分:-1)

我看到你已经接受了答案,但是处理实际结构问题并且不使用触发器或检查约束的替代方法是在Make和Model表中创建虚拟条目“n / a”或类似的描述,分别为Type和Make中的每个条目,然后去掉Vehicle中的冗余列。

这样,如果你知道的只是车辆的类型,你会在Make中找到引用相应类型的虚拟条目,然后在模型中找到引用该Make的虚拟条目,然后从中引用该模型。车辆中的新行。

当然,主要的缺点是在添加Type或Make时提前创建虚拟行的额外内务处理,或者在添加缺少数据的Vehicle时按需提供。