我记得在播客014中听到Joel Spolsky提到他几乎从未使用过外键(如果我没记错的话)。然而,对我来说,它们对于避免数据库中的重复和后续数据完整性问题非常重要。

人们是否有一些可靠的理由(以避免与Stack Overflow原则一致的讨论)?

编辑:“我还没有创建外键的理由,所以这可能是我真正建立一个外键的第一个理由。”


当前回答

更新:我现在总是使用外键。对于反对意见“他们使测试变得复杂”,我的回答是“编写单元测试,这样他们就根本不需要数据库。任何使用该数据库的测试都应该正确地使用它,这包括外键。如果准备工作很痛苦,那就找一种不那么痛苦的方式来做。”


外键使自动化测试复杂化

假设您正在使用外键。您正在编写一个自动测试,该测试表示“当我更新财务帐户时,它应该保存交易记录。”在这个测试中,您只关心两个表:帐户和事务。

但是,accounts对契约有一个外键,契约对客户有一个fk,客户对城市有一个fk,城市对州有一个fk。

现在,数据库将不允许您运行测试,除非在四个与测试无关的表中设置数据。

至少有两种可能的观点:

“这是一件好事:你的测试应该是现实的,这些数据限制将存在于生产中。” “这是一件坏事:你应该能够在不涉及其他部分的情况下对系统的各个部分进行单元测试。您可以为整个系统添加集成测试。”

也可以在运行测试时暂时关闭外键检查。至少MySQL支持这一点。

其他回答

我同意前面的答案,因为它们对维护数据一致性很有用。然而,Jeff Atwood几周前发表了一篇有趣的文章,讨论了规范化和一致性数据的利弊。

简而言之,在处理大量数据时,非规范化数据库可以更快;你可能不关心精确的一致性取决于应用程序,但它迫使你在处理数据时更加小心,因为DB不会。

澄清数据库是一个没有主键或外键的商业数据库示例。

http://www.geekinterview.com/question_details/18869

有趣的是,技术文档花了很大的篇幅来解释表是如何关联的,用什么列来连接它们等等。

换句话说,它们本可以使用显式声明(DRI)连接表,但它们选择不这样做。

因此,澄清数据库充满了不一致,性能不佳。

但我认为它使开发人员的工作更容易,不必编写代码来处理引用完整性,例如在删除或添加之前检查相关行。

我认为,这就是关系数据库中没有外键约束的主要好处。它使开发变得更容易,至少从不顾一切的角度来看是这样。

One time when an FK might cause you a problem is when you have historical data that references the key (in a lookup table) even though you no longer want the key available. Obviously the solution is to design things better up front, but I am thinking of real world situations here where you don't always have control of the full solution. For example: perhaps you have a look up table customer_type that lists different types of customers - lets say you need to remove a certain customer type, but (due to business restraints) aren't able to update the client software, and nobody invisaged this situation when developing the software, the fact that it is a foreign key in some other table may prevent you from removing the row even though you know the historical data that references it is irrelevant. After being burnt with this a few times you probably lean away from db enforcement of relationships. (I'm not saying this is good - just giving a reason why you may decide to avoid FKs and db contraints in general)

对我来说,如果您想要遵循ACID标准,那么拥有外键以确保引用完整性是至关重要的。

我只知道Oracle数据库,不知道其他数据库,而且我知道外键对于保持数据完整性是必不可少的。在插入数据之前,需要建立一个数据结构,并且建立正确的数据结构。当这一步完成时——所有的主键和外键都创建好了——工作就完成了!

意思是:孤立的行?不。这辈子都没见过。除非一个糟糕的程序员忘记了外键,或者他在另一个层次上实现了外键。在Oracle的环境中,这两者都是巨大的错误,会导致数据复制、孤儿数据,从而导致数据损坏。我无法想象一个没有强制FK的数据库。在我看来是一片混乱。这有点像Unix权限系统:假设每个人都是root用户。想想混乱吧。

外键是必不可少的,就像主键一样。这就像是说:如果我们移除主键会怎样?那么,整个混乱将会发生。这是什么。不能将主键或外键的职责移到编程级别,但必须移到数据级别。

缺点呢?是的,当然!因为在插入时,会有更多的检查。但是,如果数据完整性比性能更重要,那么这是显而易见的。Oracle上的性能问题更多地与索引有关,索引包含PK和FK。