【问题标题】:Database Design w/ Foreign Keys Question带外键的数据库设计问题
【发布时间】:2009-11-13 23:28:38
【问题描述】:

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

假设您要建立一个包含类型(汽车、卡车等)、品牌和型号的车辆数据库。用户必须至少输入 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 以确保类型、品牌和型号都匹配?例如,您将如何防止车辆出现(类型:摩托车、制造商:福特、型号:思域)?其中每一个都是有效的 FK,但它们不维护通过其他表的 FK 显示的关系。

另外,由于不需要 Model,我不能只存储 model_id FK 并从它向后工作。

我完全不受数据库设计的束缚,因此我愿意改变表的设置方式。有什么想法吗?

附: - 如果有人感兴趣,我正在使用 mysql,但这更多是关于数据库的一般问题。

编辑(澄清):

-type_id 和 make_id 在车辆表中是必需的,除非在 model_id 为 null 的情况下有办法找出它们;

——需要维护type_id、make_id和model_id之间的关系。

【问题讨论】:

  • 您的 Vehicle 表中不需要列 make_id 和 type_id。

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


【解决方案1】:

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

但是,正如其他答案所表明的那样,您真正应该存储的只是车辆模型。在您的应用程序中,您应该深入了解类型(如果可用)。

【讨论】:

  • 我基本上可以用触发器来模拟吗?
  • 是的,我已经修改了答案。
【解决方案2】:

像这样:

类型:

  • id (PK)
  • 说明

制作:

  • id (PK)
  • type_id(FK 引用 Type:id,不为空)
  • 说明

型号:

  • id (PK)
  • make_id(FK 引用 Make:id,不为空)
  • 说明

车辆:

  • id (PK)
  • model_id(FK 引用 Model:id)

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

想一想:如果车辆有给定的型号,但车辆和型号都有品牌,那么这些值可能不同。由于信息冗余,这种不一致可能会发展。您通常希望避免这种情况。

如果您需要确定车辆的品牌和类型,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

等等。

【讨论】:

  • 谢谢,但不幸的是,这只解决了部分问题(尽管这是主要问题)。如果没有给出模型,则无法回溯到车辆的类型或制造。我同意参考车辆的品牌和类型似乎是一个潜在的麻烦来源。我在想(希望)我只是错过了一些东西。
  • 你的SQL好像没有解决make为NULL的问题。我错过了吗?
  • 你需要清楚你在建模什么。模特有品牌吗?还是车辆有品牌?我可以两者兼而有之,但您会遇到问题(如上所列)。此外,Make 在上面的模型上强制执行。
【解决方案3】:

这是一种方法:

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

模型表包含所有模型共有的列;而汽车、卡车和摩托车都有各自特定的列。

在为数据库建模时,请考虑数据、实体和关系;不要从 UI 开始——中间有一个业务层来解决问题。可以使用 MySQL,您可以在应用层上强制检查和外键约束。

【讨论】:

    【解决方案4】:

    您的设计适合数据完整性,您的应用程序将负责维护车辆必须由特定类型的品牌和特定品牌的模型组成。

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

    【讨论】:

    • 谢谢。这基本上就是我所拥有的(执行检查的应用程序)。如果可能的话,我想把它移到数据库中,所以我会调查一下。
    • MySQL 目前不强制执行 CHECK 约束。
    【解决方案5】:

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

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

    当然,主要的缺点是额外的内部管理来创建虚拟行,或者在添加类型或品牌时提前,或者在添加缺少数据的车辆时按需添加。

    【讨论】:

      猜你喜欢
      • 2011-04-14
      • 1970-01-01
      • 2014-06-02
      • 2011-08-17
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      相关资源
      最近更新 更多