【问题标题】:Is it OK to use 2 foreign keys in a table, one of which must be null?在一个表中使用 2 个外键是否可以,其中一个必须为空?
【发布时间】:2013-07-10 01:23:16
【问题描述】:

如果我有一个表,其中每一行都是客户预订,那么在这个表中是否可以有 2 个外键:一个为空,另一个引用适当的主键。我有两个表应用了外键约束的原因是预订可以是服务包 (service_package) 或单个服务 (service) 的预订。

我的猜测是,这是一个糟糕的设计,因为可以在同一预订行中注册两种预订,除非通过使用函数或存储过程来实施限制。

此解决方案是否可行或有更好的方法来执行此操作,例如为所提供的服务创建更通用的表?

【问题讨论】:

    标签: mysql sql null foreign-keys


    【解决方案1】:

    这是一个合理的方法。当特定列的值为 NULL 时,连接将失败。

    在 MySQL 中,您必须使用触发器强制执行此操作。其他数据库具有“检查约束”的概念,您可以在其中强制填充两个值中的一个。

    如果您有更多列,您可能会想切换到“类型”列和“id”。这要求所有 id 都具有相同的类型。它还需要一个触发器来确保正确填充列。而且,在进行连接时可能会导致错误。

    在这两种选择中,我更喜欢你的方法只处理两个 id。

    【讨论】:

    • 谢谢!由插入的各个 FK 的触发器强制执行的“1 null FK + 1 not null FK”似乎适用于这种情况。然而,尝试创建一个不依赖触发器进行正确归一化的模型是很诱人的,但我想这属于阻抗不匹配类别。如果有某种非此即彼的符号可以应用于这些 FK,那就太好了,类似于我们在 OO 建模中所拥有的。也许我可以将 {OR} 或 {EXCLUSIVE} 或类似于关系线添加到 FK 引用的相应表中。
    【解决方案2】:

    虽然具有可为空的 FK 并没有错,但从性能的角度来看并不总是可取的。正如post 中正确提到的那样:

    B-tree 索引对于高基数数据(即具有许多可能值的列,其中列中的数据是唯一的或几乎唯一的)最有效。如果您将有许多 NULL 值(或任何其他重复值),则查询优化器可能会选择不使用索引来过滤结果集的记录,因为执行表扫描会更快。

    我会选择使用复合索引 (id,type) 的 type/id 列。

    【讨论】:

    • 谢谢!有趣的表现点。一旦我阅读了关系数据库的更多技术方面,这些可能会派上用场。目前,我主要关心的是使数据库结构尽可能的连贯、安全和易于维护。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 2014-08-27
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    相关资源
    最近更新 更多