2010-08-08 177 views
7

我正在构建一个小应用程序并设置表之间的外键关系。然而我很困惑,为什么我真的需要这个?有什么好处 - 在编写我的查询时是否可以帮助我,而不必执行任何连接?以下是我的数据库的示例代码片段:外键 - 他们为我做了什么?

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

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

users之间有一个关键关系。 user_idprojectscreator

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

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

由于MySQL的应该知道表之间的关系?如果不是,那么在数据库设计中外键的真正功能是什么?

+0

如果这被迁移到http://dba.stackexchange.com/? – simgineer 2015-06-01 20:47:48

+0

不,可能不是。在该网站存在之前,它曾被问及回答。迁移没有真正的优势。 – 2015-06-01 20:49:00

回答

16

外键提供了参照完整性。外键列中的数据将被验证 - 该值只能是在外键中定义的表&列中已经存在的值。它在停止“坏数据”方面非常有效 - 有人无法输入他们想要的任何内容 - 数字,ASCII文本等。这意味着数据已经过标准化 - 重复值已被识别并与他们自己的表格隔离,因此没有更多顾虑关于处理文本中的区分大小写...以及这些值是一致的。这导致了下一部分 - 外键是您用来将表连接在一起的东西。

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

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

谢谢 - 我想我可以通过这种方式从连接中获得一种方式 - 但你回答有助于描述这到底是什么。 – 2010-08-08 16:27:09

0

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

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

如果项目可以有许多用户和用户可以属于许多项目,那么你有多对多的关系,你需要一个更复杂的模型。

+0

我已经设置了大量的数据库设计而不创建任何外键,并且它们使用了一对多的关系。我想知道外键为我做了什么,我离不开它们。 – 2010-08-08 16:05:14

+0

鉴于上面的表格布局,你会有什么SQL语句可以得到所有谁是PROJECT_ID = 1的一部分的用户? – EddieC 2010-08-08 16:13:16

+1

@Marco Ceppi:当您建模的关系,而不使用外键,没有什么可以进入不相关成表示关系的列(或多个)数据停止用户。 – 2010-08-08 16:14:09

4

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

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

+2

我会说数据验证是功能性的 - 外键约束就像steriods上的CHECK约束。 CHECK约束只验证数据;外键意味着您可以将相关信息添加到该关系中 - 除了数据验证外。 – 2010-08-08 16:39:38

3

如果你永远不会加入,你不需要外键。

想想吧,如果你永远不会加入,你不需要关系数据库! (小笑话)严重的是,如果你有多个表,你最好学习如何使用连接,以及如何将外键设计为模式。

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


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

在发动机提供的连接条件语言是可能的。一个只需要看看Microsoft Access中的图形查询设计工具。一旦将所有可访问关系声明为Access,就可以从多个表中提取数据,而无需再次指定连接条件。访问自动计算出来。

如果一个建立在访问两个表查询,然后切换到SQL视图,一看就会访问已实际上创造了一个联接条件联接。这种功能在基于字符的语言中也是可能的,但SQL不是这样的语言。

我顺便指出,很多项目可以属于一个用户。因此,用户是上述模式中的“参考表”,而不是项目。我期望自动导航方向更容易自动从参考表查找,而不是相反。

+0

多年后,我注意到许多人使用术语“外键”来指仅具有声明外键约束的列。我不确定OP是否意味着这一点。几年前,当我学到这些东西时,外键是外键,不管它是否被声明。未声明的外键是破坏参照完整性的邀请。这使得可能存在的任何性能差异超出预期。 – 2016-08-23 12:00:50

2

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

  • 防止通过防止错配密钥
  • 防止通过自动删除孤立行(与ON DELETE CASCADE)包含不一致的数据的数据库包含不一致的数据的数据库
  • 即成记录对未来开发该列是一个外键到

当然这不是马ndatory做任何这些事情,但可能会随着时间的推移提高代码质量。严格要求有关的事情通常是好的 - 它会导致更多的错误测试(因此在生产中减少)