目录

数据库CS751数据库各种连接的理解包括自然连接,内连接,外连接

【数据库CS751】数据库各种连接的理解(包括自然连接,内连接,外连接)

目录


一、前言

数据库的各种连接可能是学习数据库的时候最容易懵的点之一了。

所以今天来仔细盘一盘数据库的各种连接究竟是怎么回事。

本文使用的数据库表,都在《【数据库CS751】数据库的建表与插入》一文中有完整的SQL语句,可以去复制粘贴来一边测试一边理解。

二、自然连接 NATURAL JOIN

自然连接,是一种很自然的连接, 没有指定连接条件,但是连接语句会自动检索两个表R,S的相同名称的列,注意:我说的是

相同名称

如果不是相同名称,自然连接就会出现一些问题。

如果不是相同名称,则连接退化为笛卡尔积:

例如:现在有这样的表存在,我想让EMPLOYEE和WORKS_ON表自然连接,那么虽然Ssn与Essn是同一个意思,但是由于列名不一样,导致自然连接无法识别,就会成为笛卡尔积:

https://i-blog.csdnimg.cn/blog_migrate/9e1456c910befafb5f8725f7b7aff5dc.png

连接语句如下:

select * from employee natural join works_on

结果:筛选出来128条记录?!

https://i-blog.csdnimg.cn/blog_migrate/9ba507d694ed97d35b6051ac486cd131.png

https://i-blog.csdnimg.cn/blog_migrate/f8c6bae4f87cb703ec59feb8c42c9eb9.png

SSN与ESSN并没有合并,而且在EMPLOYEE中有8条内容,WORKS_ON中有16条

16*8 = 128, 所以可以肯定的是,当自然连接无法匹配到同样的列名称时,将退化为笛卡尔积,变成无意义的表连接。所以一定要谨慎命名列名!

但是,我们依然可以通过AS重命名的方式来规避这一问题。

三、内连接 INNER JOIN

只有在另一个关系中存在匹配的元组时,才会在结果中包含元组。

也就是说,内连接,只匹配双方都有的项,同时,内连接需要连接条件,用on引出

例如:

select * from employee inner join works_on on employee.Ssn = works_on.Essn

结果:

https://i-blog.csdnimg.cn/blog_migrate/6ca142c0a99e81d24806d957155465e0.png

https://i-blog.csdnimg.cn/blog_migrate/5bb27e89f2efb3a8caee9037746026e0.png

那么有16行匹配结果。这就与前面的自然连接失败形成鲜明对比。这也是自然连接成功时应该出现的结果。

同时,我们发现, 其实当自然连接匹配成功时就是内连接 ,这就是自然连接与内连接的关系,同时Mysql中默认的join形式就是内连接或者自然连接。

四、外连接 OUTER JOIN

那么outer join,分为左右外连接与全外连接,但是Mysql并不支持全外连接,

那么我们只说说左外连接吧:右外连接雷同

左外连接:

1.左表中的每个元组必须出现在result中

2.如果没有匹配的元组,为右表的属性添加NULL值

我们来举个例子:

我们用EMPLOYEE表左外连接DEPARTMENT表,虽然这么做没什么意义,但是我们却能清楚看到左外连接的效果:

select * from employee left outer join department on employee.Ssn = department.Mgr_ssn

https://i-blog.csdnimg.cn/blog_migrate/b1efd04e7c942b457a8af888920fb225.png

我们会发现在原DEPARTMENT的属性中出现了不匹配的项,这些项会被赋予null值

https://i-blog.csdnimg.cn/blog_migrate/34fbded30b912fdd0b68a56b7090cbc5.png

同时我们看到有8行返回,刚好等于EMPLOYEE表的行数,所以就知道,整个左外连接的过程,就是右表向左表按条件匹配的过程,没有匹配上的就给空值,匹配上的就自动连接。

右外连接基本同理。

另外,左右是相对的 ,我左外连接左表和右外连接右表其实是一样的效果。

就比如我刚刚是:

select * from employee left outer join department on employee.Ssn = department.Mgr_ssn

我现在换成右外连接:同时调换左右表位置

select * from department right outer join employee on employee.Ssn = department.Mgr_ssn

那么结果是一样的:

https://i-blog.csdnimg.cn/blog_migrate/6a2b04c4937c6b9f12bb3a41d4b91679.png

https://i-blog.csdnimg.cn/blog_migrate/f4c371f57612bbe4d4a7a86d721e8d7b.png