外键 - 他们为我做了什么?

时间:2010-08-08 15:53:24

标签: sql mysql database database-design foreign-keys

我正在构建一个小应用程序并在表之间建立外键关系。但是我很困惑为什么我真的需要这个?有什么好处 - 在编写我不需要执行任何连接的查询时,它是否有助于我?这是我的数据库的示例片段:

+-------------------+
| USERS             |
+-------------------+
| user_id           |
| username          |
| create_date       |
+-------------------+

+-------------------+
| PROJECTS          |
+-------------------+
| project_id        |
| creator           |
| name              |
| description       |
+-------------------+

usersuser_idprojects之间存在关键关系。creator

我可以执行这样的查询吗?

SELECT * FROM PROJECTS WHERE USERS.username = "a real user";

既然MySQL应该知道表之间的关系吗?如果没有,那么数据库设计中外键的真正功能是什么?

5 个答案:

答案 0 :(得分:17)

外键提供参照完整性。验证外键列中的数据 - 该值只能是表和表中已存在的值。外键中定义的列。它可以非常有效地阻止“坏数据” - 有人无法输入他们想要的任何内容 - 数字,ASCII文本等。这意味着数据已经标准化 - 重复值已被识别并隔离到他们自己的表中,因此不再需要关注关于处理文本中的区分大小写...并且值是一致的。这导致了下一部分 - 外键是用于将表连接在一起的内容。

您对用户拥有的项目的查询不起作用 - 当您没有引用查询中的表时,您正在引用USERS表中的列,并且没有用于获取该信息的子查询在将其链接到PROJECTS表之前。你真正使用的是:

SELECT p.*
   FROM PROJECTS p
   JOIN USERS u ON u.user_id = p.creator
WHERE u.username = 'John Smith'

答案 1 :(得分:5)

基本上,他们不会再提供任何功能。它们会停止任何插入或更新,从而破坏数据模型的参照完整性。

我认为另一个关键方面是他们将数据模型传达给使用它的任何其他开发人员。我经常看一下表的外键,看看数据模型如何一目了然。

答案 2 :(得分:3)

如果您从未进行过连接,则不需要外键。

想想看,如果你从不加入,你就不需要关系数据库了! (小笑话)说真的,如果你有多个表,你最好学习如何使用连接,以及如何将外键设计成模式。

正如先前的响应者所说,外键强制执行参照完整性。没有参照完整性,连接会产生神秘的结果。


我之前的回答没有注意到问题背后的真正问题。我回答的问题是“为什么SQL模式中有外键”,答案是“为了进行连接”。但是重读这个问题,我理解了一个更微妙的问题,即“为什么SQL不能为我做联接,如果它知道联系”。这是一个非常好的问题。它应该得到比上述更好的答案。

引擎提供连接条件的语言是可能的。只需要查看Microsoft Access中的图形查询设计工具即可。一旦声明了与Access的所有可交互关系,就可以从多个表中提取数据,而无需再次指定连接条件。 Access会自动识别它们。

如果在Access中构建两个表查询,然后切换到SQL视图,则会看到Access实际上创建了一个具有连接条件的连接。这种功能在基于字符的语言中也是可行的,但SQL不是这样的语言。

我顺便提一下,很多项目都属于一个用户。所以Users是上述模式中的“参考表”,而不是Projects。我希望更容易的自动导航方向是从参考表自动查找,而不是相反。

答案 3 :(得分:2)

使用外键约束可以提供以下内容:

  • 通过防止不匹配的密钥来防止包含不一致数据的数据库
  • 通过自动删除孤立行(使用ON DELETE CASCADE)防止包含不一致数据的数据库
  • 用于向未来的开发者提供哪些列是
  • 的外键的文档

当然,执行上述任何操作都不是强制性的,但可能会随着时间的推移提高代码质量。对事物严格要求通常是好的 - 它会导致更多的测试错误(因此生产更少)

答案 4 :(得分:0)

如果每个用户只属于一个项目,并且每个项目完全属于一个用户,则表示这些表具有一对一的关系并且在users.user_id和projects.project_id之间具有关键关系是可以的(尽管可能不标准)。

但是,如果用户可以属于许多项目(或者项目可以拥有许多用户),那么您将拥有一对多关系并且需要外键。

如果项目可以拥有许多用户,并且用户可以属于许多项目,那么您将拥有多对多关系,并且您需要更复杂的模型。