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

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

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


当前回答

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


外键使自动化测试复杂化

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

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

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

至少有两种可能的观点:

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

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

其他回答

它们会使删除记录变得更加麻烦——当其他表中存在外键违反约束的记录时,您就不能删除“主”记录。可以使用触发器进行级联删除。

如果不明智地选择主键,则更改该值将变得更加复杂。例如,如果我有我的“客户”表的PK作为人的名字,并使该键在“订单”表中为FK,如果客户想更改他的名字,那么这是一个巨大的痛苦……但这只是粗制滥造的数据库设计。

我相信使用火密钥的优点大于任何假定的缺点。

有一个很好的理由不使用它们:如果你不了解它们的作用或如何使用它们。

在错误的情况下,外键约束可能导致事故的瀑布式复制。如果有人删除了错误的记录,恢复它可能会成为一项艰巨的任务。

同样,相反,当您需要删除某些内容时,如果设计不当,约束可能会导致各种锁阻止您的操作。

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)

外键对于任何关系数据库模型都是必不可少的。

我可以看到使用外键的一些原因(有人提到,孤立行很烦人),但我也从不使用它们。对于一个相对正常的DB模式,我不认为它们是100%需要的。约束是好的,但我认为通过软件来实施约束是更好的方法。

亚历克斯