链接表是否可以有两个互斥的列?

时间:2010-11-03 22:29:31

标签: mysql database-design foreign-keys constraints

我遇到一个问题,由于之前人们的设计决策不好,我不得不在链接表中有两列应该始终是互斥的。我见过SQL-Server: Define columns as mutually exclusive但是MySQL没有强制执行CHECK约束,所以我正在寻找其他选项。有没有办法在两列之间强制互斥?

让我解释一下如果有人看到更好的解决方案。

以前的dev / admins构建了两个基本相同类型的表。我有一个新的表1 - >理论上很多都是他们所代表的东西。所以我的两个选项似乎是创建两个桥接表或一个带有两个外部键引用的桥接表。对于我来说,这两个表似乎是一个丑陋的解决方案,我希望避免这种解决方案,但是未实施的相互排斥的领域让我容易受到腐败的打击。

具体例子,因为我不能分享我的真实案例:

Table 'full_time_students' stores full time students
Table 'part_time_students' store part time students

Table 'class' will store class info
Table 'class_students' should store which students are in which class

在一个理想的世界中,我会将两个学生表结合起来,但是有很多代码会破坏,我没有时间/意愿去修复所有这些,所以我现在被迫处理现有的模式/数据。我正在使用InnoDB所以我已经计划在student_ids上设置外键约束,但就像我说的那样,如果我用一个列有两个列,我会打开自己的行,同时有两行ID。

写出来几乎说服我重新考虑2表解决方案......

3 个答案:

答案 0 :(得分:5)

在回复评论时重写。

我不同意任何答案。

没有什么可以担心“更多”表,这是关系数据库的本质;特别是如果你想要Relational的强大功能,并允许用户访问数据库而无需通过你的应用程序。

我假设有两件事:

  1. 您认为之前的开发者犯了一个错误,因为StudentFullTime和StudentPartTime应该合并为学生,因为他们有很多共同的列

  2. 您有一个新的需求类需要Class和Student之间的多对多关系。

    • 在关系术语中,称为关联表:在逻辑模型中,它显示为n :: n关系(无表);在物理模型中,它呈现为表格。 (当然,如果它有列,那么它会在逻辑模型中显示为实体,而不是关系。)
  3. 好的,(1)不正确。正如将未标准化的公共列放入单个表中是错误的,使单个表具有不适用的列(Nullable列)也是错误的。他们应该做的是实施三个表;不是一个;而不是两个,在普通的子类型超类型集群中。

    • 超类型包含公共列和一个微分器,每个子类型包含专用的列。超类型和子类型之间的关系是一对一的。这是非常强大的,因为(a)它消除了歧义(存在于单个非规范化表中),(b)消除了空值,(c)最重要的是,允许这些私有列上的任何索引简单而独特(到期)缺乏空值。)

      • 我的所有数据模型都符合 IDEF1X 标准。为了帮助那些不熟悉IDEF1X的人,这里有一个解释 IDEF1X Notation 文档的文档。如果你不明白圆圈,酒吧和乌鸦脚是什么意思;或什么是关系线上的意味着;或者为什么水平线就在哪里,请现在阅读。

    Normalised Before

    所以你来了,你需要实现(2)。生活对所有人来说都很容易,因为数据库是规范化的:你可以添加你需要的东西而不必改变现有的表结构,或者扰乱任何现有的代码。

    Normalised After

    但是他们没有这样做,他们在“数据库”中留下了两个Unnormalised表。

    所以你来了,你需要实现(2)。在寻找“互斥”列时,您已经确定了标准化错误(在您身边)。您需要的n :: n关联表实际上是具有学生的类;在确认基本需求后,他们可能是FullTime或PartTime的事实是一个令人担忧的进展。在考虑到这种需求之后,当然,你必须实现能够处理两种类型学生的东西。

    • 如果你实现了一个表,这是一个严重错误,你需要一个可以做有趣事情的dbms,如“互斥”

    • 如果您实现了两个表,那么您只是在复合它们的错误。这将最终受到限制,你的SQL代码将是丑陋的。

    Their Error Progressed by You

    所要求的是,让你在你身边规范化,从而避免阻碍数据库的力量。

    Normalised Yours

    • 关联表的一个表,以及两个子类型的一个表(基于两个子标准表的存在)。简单的子类型超类型1 :: 1集群。

    • No Nulls,Full integrity,FKs,referenceability等。每个表上的简单唯一索引。想想你的代码会是什么样子。

    • 如果不是现在,那么在将来,当您需要将列添加到关联表时(就像您今天需要添加表一样),您可以将它们添加到一个位置。如果你复制了他们的错误,你必须将这些列放在两个地方。

    请迁移现有的密钥,它们已经足够了,它们已经有了意义,不要创建新的IDENTITY密钥。

答案 1 :(得分:1)

这是一个解决问题而不破坏很多代码的想法。创建一个新表格的学生,并使用其他表格和标志字段填充数据,以指示完整或兼职。然后创建具有全日制学生和兼职学生表名称的视图。这意味着所有选择仍然可以正常工作,您只需修复插入和更新代码即可转到新表。

或者您可以在触发器中强制执行规则。

答案 2 :(得分:0)

在MySQL之前使用MySQL中的触发器实施业务规则:

Throw an error in a MySQL trigger