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

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

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


当前回答

“它们会使删除记录变得更加麻烦——你不能删除“主”记录,而其他表中的记录中有外键会违反这种约束。”

重要的是要记住,SQL标准定义了删除或更新外键时所采取的操作。 我所知道的是:

ON DELETE RESTRICT - Prevents any rows in the other table that have keys in this column from being deleted. This is what Ken Ray described above. ON DELETE CASCADE - If a row in the other table is deleted, delete any rows in this table that reference it. ON DELETE SET DEFAULT - If a row in the other table is deleted, set any foreign keys referencing it to the column's default. ON DELETE SET NULL - If a row in the other table is deleted, set any foreign keys referencing it in this table to null. ON DELETE NO ACTION - This foreign key only marks that it is a foreign key; namely for use in OR mappers.

这些相同的操作也适用于ON UPDATE。

默认值似乎取决于您使用的sql server。

其他回答

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)

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

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

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

在DB2中,如果使用mqt(物化查询表),优化器需要外键约束才能为任何给定的查询选择正确的计划。由于元数据包含基数信息,优化器会大量使用元数据来决定是否使用MQT。

我也听过这种说法——有些人忘记在外键上放索引,然后抱怨某些操作很慢(因为约束检查可以利用任何索引)。所以总结一下:没有好的理由不使用外键。所有现代数据库都支持级联删除,所以…

我不得不在这里第二多的评论,外键是必要的项目,以确保你有完整的数据。ON DELETE和ON UPDATE的不同选项将允许你绕过一些人们在这里提到的关于它们的使用的“下降”。

我发现在我99%的项目中,我会使用FK来加强数据的完整性,然而,在很少的情况下,我的客户必须保留他们的旧数据,不管它有多糟糕....但后来我花了很多时间写代码,只得到有效的数据,所以它变得毫无意义。