定义外键有啥好处

Posted

技术标签:

【中文标题】定义外键有啥好处【英文标题】:what are the advantages of defining a foreign key定义外键有什么好处 【发布时间】:2012-04-28 07:31:39 【问题描述】:

在使用处理关系的 MVC 框架时定义外键有什么好处?

我正在使用带有允许模型定义与关系的框架的关系数据库。因为外键是通过模型定义的,所以外键似乎是多余的。在开发中管理应用程序的数据库时,编辑/删除使用外键的表是一件麻烦事。

完全放弃使用外键有什么好处吗?

【问题讨论】:

外键关系在数据层强制执行数据完整性,从而减少进入系统的不良数据;不,不是。例如,如果您有一个与性别表具有 FK 关系的人员表,则开发人员可以将一条记录插入到性别为“whocares”的人员中。现在,您可能不在乎这一点,但是如果您根据有效条目构建逻辑并且只期望 male/female ,那么……您会遇到问题。如果您想对数据库进行逆向工程以获得 ERD,那么您也会遇到问题。和脚手架和其他技术在这个设计水平上中继...... 高度相关:Why are foreign keys more used in theory than in practice? 我曾经工作过的地方也遇到过类似的情况:一个应用程序没有外键,因为 ORM 处理了所有这些事情等等。有一天,一位非常重要的客户发现了重大的数据丢失,最终被追踪到回到 ORM 中的一个错误。对这种关系非常有害,责备 ORM 开发人员无济于事。很快就添加了外键! 为什么有人对这个问题和每个答案都投了反对票? 【参考方案1】:

带有约束的外键(在某些数据库引擎中)为您提供低级别(数据库级别)的数据完整性。 这意味着您不能实际创建不满足关系的记录。 这只是一种更安全的方法。

【讨论】:

另一个优点是级联删除。例如,假设您有一个 User 表和一个 Class 表。无需重写 Class 中的所有用户数据,您只需引用用户的 id。但是,如果该用户被删除怎么办?如果您没有打开级联删除,则类表中的行指向不存在的用户。如果该用户 ID 被完全不同的用户替换怎么办?那是事情变得非常糟糕的时候。级联删除将删除与该用户关联的所有记录。这可能看起来并不重要,但如果User 连接到很多表,这会很有帮助。 我们有任何费用吗?【参考方案2】:

它为您提供在数据库级别强制执行的数据完整性。这有助于防止可能导致无效数据的应用程序逻辑错误。

如果在 SQL 中直接完成任何绕过应用程序逻辑的数据操作,它还可以防止破坏这些约束的不良数据。

另一个好处是它允许工具自动生成数据库图表,其中包含从模式本身推断的关系。现在理论上所有图表都应该在创建数据库之前完成,但是随着数据库的发展超出其最初的化身,这些图表通常不会保持最新,并且从现有数据库生成图表的能力对双方都有帮助审查,以及向加入项目的新开发人员解释结构。

在数据库结构仍在变化时禁用 FK 可能会有所帮助,但当架构更加稳定时,它们是很好的保障。

【讨论】:

【参考方案3】:

外键保证匹配的记录存在于外表中。想象一个名为Books 的表在名为Authors 的表上有一个FK 约束。保证每本书都有Author

现在,您可以进行如下查询:

SELECT B.Title, A.Name FROM Books B
INNER JOIN Authors A ON B.AuthorId = A.AuthorId;

如果没有 FK 约束,缺少 Author 行将导致整个 Book 行被删除,从而导致数据集中缺少书籍。

此外,使用 FK 约束,尝试删除至少被一本书引用的作者将导致错误,而不是损坏您的数据库。

【讨论】:

【参考方案4】:

虽然在处理开发/测试数据时它们可能会很痛苦,但它们在生产中为我省去了很多麻烦。

将它们视为维护数据完整性的一种方式,尤其是作为防止孤立记录的保护措施。

例如,如果您有一个将许多PhoneNumber 记录与Person 相关联的数据库,那么当Person 记录因某种原因被删除时,PhoneNumber 记录会发生什么情况? 它们仍将存在于数据库中,但与它们相关的 Person 的 ID 将不再存在于相关的 Person 表中,并且您有孤立的记录。

是的,您可以编写一个触发器来在 Person 被删除时删除 PhoneNumber,但如果您不小心删除了 Person 并需要回滚,这可能会变得一团糟。

是的,您可能记得手动删除 PhoneNumber 记录,但是您在 9 个月后编写的其他开发人员或方法呢?

通过创建确保任何PhoneNumber 与现有Person 相关联的外键,您既可以确保不会破坏这种关系,也可以为预期的数据结构添加“线索”。

【讨论】:

【参考方案5】:

主要好处是数据完整性和级联删除。当它们被定义并且这些字段被正确索引时,您还可以获得性能提升。例如,您将无法创建不属于联系人的电话号码,或者当您删除联系人时,您可以将其设置为自动删除他们的所有电话号码。是的,您可以在您的 UI 或中间层中建立这些连接,但如果有人使用 SQL 而不是您的 UI 直接针对服务器运行更新,您仍然会遇到孤立的问题。 “麻烦”部分只是迫使您在进行批量更改之前考虑这些联系。 FK 救了我很多次。

【讨论】:

以上是关于定义外键有啥好处的主要内容,如果未能解决你的问题,请参考以下文章

Eloquent - 如果外键有行,则防止删除数据 - Laravel

Django admin内联显示但外键有相反的关系

Django - 有啥方法可以立即获取外键对象?

保存的JAVA报错,帮忙看看,应该是主表里的主键跟明细表里的外键有问题了

做项目时应怎样注意外键关系

SQL中怎么向外键中插入数据