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

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

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


当前回答

验证外键约束需要一些CPU时间,因此有些人省略外键以获得额外的性能。

其他回答

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

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

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

在这里回答问题的许多人都过于关注通过引用约束实现的引用完整性的重要性。在具有引用完整性的大型数据库上工作性能不佳。Oracle似乎特别不擅长级联删除。我的经验法则是,应用程序永远不应该直接更新数据库,而应该通过存储过程更新。这将代码库保存在数据库中,并意味着数据库保持其完整性。

在许多应用程序可能正在访问数据库的地方,由于引用完整性约束确实会出现问题,但这取决于控件。

还有一个更广泛的问题,应用程序开发人员可能有非常不同的需求,而数据库开发人员可能并不那么熟悉。

使用外键的原因:

you won't get Orphaned Rows you can get nice "on delete cascade" behavior, automatically cleaning up tables knowing about the relationships between tables in the database helps the Optimizer plan your queries for most efficient execution, since it is able to get better estimates on join cardinality. FKs give a pretty big hint on what statistics are most important to collect on the database, which in turn leads to better performance they enable all kinds of auto-generated support -- ORMs can generate themselves, visualization tools will be able to create nice schema layouts for you, etc. someone new to the project will get into the flow of things faster since otherwise implicit relationships are explicitly documented

不使用外键的原因:

you are making the DB work extra on every CRUD operation because it has to check FK consistency. This can be a big cost if you have a lot of churn by enforcing relationships, FKs specify an order in which you have to add/delete things, which can lead to refusal by the DB to do what you want. (Granted, in such cases, what you are trying to do is create an Orphaned Row, and that's not usually a good thing). This is especially painful when you are doing large batch updates, and you load up one table before another, with the second table creating consistent state (but should you be doing that sort of thing if there is a possibility that the second load fails and your database is now inconsistent?). sometimes you know beforehand your data is going to be dirty, you accept that, and you want the DB to accept it you are just being lazy :-)

我认为(我不确定!)大多数已建立的数据库都提供了一种指定外键的方法,这种方法不是强制的,只是一些元数据。由于不强制执行消除了不使用fk的所有理由,如果第二部分中的任何理由适用,您可能应该走那条路。

跨应用程序生命周期的可维护性和稳定性如何?大多数数据的生命周期都比使用它的应用程序长。关系和数据完整性非常重要,不能寄希望于下一个开发团队在应用程序代码中做出正确的处理。如果您没有使用过不尊重自然关系的脏数据的db,那么您将会使用。数据完整性的重要性将变得非常清楚。

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