我正在构建一个小型应用程序,并在表之间设置外键关系。但是我很困惑为什么我真的需要这个?它的优点是什么?它是否有助于我编写查询,而不必执行任何连接?下面是我的数据库的一个示例片段:
+-------------------+
| USERS |
+-------------------+
| user_id |
| username |
| create_date |
+-------------------+
+-------------------+
| PROJECTS |
+-------------------+
| project_id |
| creator |
| name |
| description |
+-------------------+
users
之间存在关键关系。user_id
和projects
。creator
我能像这样执行查询吗?SELECT * FROM PROJECTS WHERE USERS.username = "a real user";
既然MySQL应该知道表之间的关系?如果不是,那么外键在数据库设计中的真实的功能是什么?
6条答案
按热度按时间0s0u357o1#
外键提供参照完整性。验证外键列中的数据-值只能是外键中定义的表和列中已经存在的值。它在阻止“坏数据”方面非常有效--有些人不能输入他们想要的任何东西--数字、ASCII文本等。这意味着数据是规范化的-重复值已被识别并隔离到自己的表中,因此不再需要担心处理文本中的大小写敏感性。并且值一致。这将进入下一部分-外键是用来将表连接在一起的。
您对用户拥有的项目的查询将不起作用-您引用的是
USERS
表中的列,而查询中没有对该表的引用,并且在将其链接到PROJECTS
表之前没有使用子查询来获取该信息。你真正需要的是:jv4diomz2#
基本上,他们不会给予你任何更多的功能。它们阻止任何破坏数据模型的引用完整性的插入或更新。
在我看来,另一个关键的方面是他们将数据模型传达给任何其他使用它的开发人员。我经常查看表具有哪些外键,以便一目了然地了解数据模型是如何组合在一起的。
ffscu2ro3#
如果你从来不做连接,你就不需要外键。
想想看,如果你从来不做连接,你就不需要关系数据库!(小笑话)说真的,如果你有多个表,你最好学习如何使用连接,以及如何将外键设计到模式中。
正如前面的响应者所说,外键强制引用完整性。如果没有引用完整性,联接会产生神秘的结果。
我之前的回答没有注意到问题背后的真实的问题。我回答的问题是“为什么SQL模式中有外键”,答案是“为了进行连接”。但是重读这个问题,我理解了一个更微妙的问题,那就是“为什么SQL不能为我做连接,如果它知道链接的话”。这是一个非常好的问题。它值得一个比上面更好的答案。
引擎提供连接条件的语言是可能的。只需查看Microsoft Access中的图形查询设计工具。一旦向Access声明了所有表间关系,就可以从多个表中提取数据,而无需重新指定连接条件。Access会自动计算出来。
如果在Access中构建两个表的查询,然后切换到SQL视图,则会看到Access实际上创建了一个具有连接条件的连接。这种能力在基于字符的语言中也是可能的,但SQL不是这样的语言。
我顺便指出,许多项目可以属于一个用户。因此Users是上述模式中的“引用表”,而不是Projects。我希望更容易的自动导航方向是从引用表中自动查找,而不是相反。
ruarlubt4#
使用外键约束可以提供以下功能:
当然,这并不是强制性的,但随着时间的推移,它可能会提高代码质量。严格要求通常是好的--这会导致测试中更多的错误(因此在生产中更少)
nvbavucw5#
如果每个用户都属于一个项目,而每个项目都属于一个用户,那么可以说这些表具有一对一的关系,并且在users.user_id和projects.project_id之间具有键关系(尽管可能不是标准的)。
但是,如果一个用户可以属于多个项目(或者一个项目可以有多个用户),那么您就有一个一对多的关系,您需要一个外键。
如果项目可以有多个用户,而用户可以属于多个项目,那么就存在多对多关系,需要一个更复杂的模型。
cigdeys36#
外键强制引用完整性。我们也可以指向另一个表中的某个元组,而不将列设置为外键,但这不会给我们提供引用完整性,也严重缺乏表达能力,并且我们不会获得Reactions等外键提供的所有其他功能。在表上定义外键时,不能插入会违反定义的引用完整性的数据。最好的做法是设置Reactions,以了解当被引用的元组/实体被删除或更新时会发生什么。这些列经常在JOIN的条件下使用。
我能像这样执行查询吗?
你首先要加入表中提到的接受的答案。