定义外键有啥好处
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