1、概述
连接是(JOIN) 是根据两个或者多个表之间的列建立关系, 获取所需要的数据,在Oracle数据库中,提供了自连接也称内连接(inner join或者join),自然连接(natural join),左连接(left join或者left outer join ),右连接(right join或者 right outer join),全连接(full join或者 full outer join)以及笛卡尔积(cross join)
基本语法:select table1.column,table2.column from table1 [inner | left | right | full ] join table2 on table1.column1 = table2.column2;
为了更好的再后面阐述:我们首先建立了stu以及class两张表如下:
STU表如下:
create table stu( stu_id varchar2( 10), name varchar2(10 ), class_id varchar( 10) );
STU表中数据为:
CLASS创建如下:
create table class( class_id varchar2( 10), class_name varchar2( 10) );
数据有:
2、Oracle连接
2.1、内连接(inner jion)
Oracle 的join连接默认就是inner join,所以在写内连接时可以把inner省略, 这种连接返回的是两表交集的部分,即如果表中至少有一行匹配则但会行。可以用下面蓝色部分表示:
我们用实例来说明什么是内连接,我们可以在表stu和表class 通过class_id建立连接如下,下面三种方式是等价的:
select s.stu_id,s.name,s.class_id,c.class_name from stu s, class c where s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s inner join class c on s.class_id =c.class_id order by stu_id ;
我们可以看到结果返回的是两表中class_id相同的那些记录:
用inner jion中我们是根据两表中的class_id字段来匹配,还有一种连接可以根据量表自动去匹配相同的字段,并返回数据行,这种连接称作 自然连接(natural join),我们可以把它看成是内连接的一种,用法如下:
select stu_id,name ,class_id,c.class_name from stu s natural join class c
自然连接需要注意一下亮点:
1、如果自然连接的多个字段的名称和类型都匹配,那么他们都会作为自然连接的连接条件;
2、若自然连接的连个表仅字段相同,但是类型不同将会返回一个错误。
2.2、外连接
在Oracle中外连接主要有 左外连接、右外连接以及全连接三种
2.2.1、左外连接(left join或者left outer join)
左外连接:返回的记录行数与左表相同,即使右表中没有匹配行,也从左表中返回所有行;如下图所示:
在oracle中,我们可以建立左连接如下,以下这三种方式建立的左连接时等价的:
select s.stu_id,s.name,s.class_id,c.class_name from stu s left join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s left outer join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s ,class c where s.class_id =c.class_id(+) order by stu_id;
返回记录行如下,从返回结果中可以看出左连接返回了stu的所有行,如class表中无数据的字段则为null
说明:
1、使用(+)建立左连接时,只能在where 条件中使用,且(+)要放在右表后
2、当使用(+)建立左连接时,如果where 有多个条件那么所有的条件都要加上(+)
3、
(+)只使用列,不适合用在表达式上
4、(+)不能和in、not in 以及 or 操作符一起使用
5、(+)只适用左连接和右连接,不能实现全连接, 但是可以通过 左连接 UNION 右连接实现。
2.2.2、右连接(right join或者right outer join)
右连接会返回右表中的所有行,即使左表中没有匹配行,也返回右表的所有行,如下图所示:
类似左连接,在oracle中实现右连接有一下几种方式,它们亦是等价的:
select s.stu_id,s.name,s.class_id,c.class_name from stu s right join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s right outer join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s , class c where s.class_id(+) =c.class_id order by stu_id ;
返回的记录行是如下,
返回结果中可以看出左连接返回了class的所有行,如stu表中无数据的字段则为null
说明:当用(+)表示右连接时,说明基本和左连接一样,只是(+)需要用在左表的字段上。
2.2.3、全连接(full join 或者full outer join)
全连接:返回的是两表的全集,无论匹配不匹配都返回行,如下图所示:
在oracle实现全连接的方式如下,下面这两种方式是等价的:
select s.stu_id,s.name,s.class_id,c.class_name from stu s full join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s full outer join class c on s.class_id =c.class_id order by stu_id ;
返回的记录行如下,两表中没匹配且在其中一张表无数据,返回null
说明:全连接不能用(+)表示,但是可以用左连接 UNION 右连接表示,注意:使用的不是UNION ALL(请参考UNION 与UNION的区别)
select s.stu_id,s.name,s.class_id,c.class_name from stu s , class c where s.class_id =c.class_id(+) union select s.stu_id,s.name,s.class_id,c.class_name from stu s , class c where s.class_id(+) =c.class_id order by stu_id ;
2.3、笛卡尔积(cross join)
笛卡尔积 :返回的是两表的乘积,返回的行数为两表各自行数的乘积,使用方法如下:
select s.stu_id,s.name,s.class_id,c.class_name from stu s cross join class c
可以得到返回的记录为:
补充:
还有一种oracle并没有关键字的连接,用使用等值以外的条件作为连接条件,可以表示如下:
3、总结
可以把以上各个连接用一张图表示(这张图是引用别人的博客,具体博客地址没找到,对原作者十分抱歉)
把之前的sql也整理如下:
--jion inner join select s.stu_id,s.name,s.class_id,c.class_name from stu s,class c where s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s inner join class c on s.class_id =c.class_id order by stu_id ; -- left jion select s.stu_id,s.name,s.class_id,c.class_name from stu s left join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s left outer join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s ,class c where s.class_id =c.class_id(+) order by stu_id ; --right jion select s.stu_id,s.name,s.class_id,c.class_name from stu s right join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s right outer join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s , class c where s.class_id(+) =c.class_id order by stu_id ; --full jion select s.stu_id,s.name,s.class_id,c.class_name from stu s full join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s full outer join class c on s.class_id =c.class_id order by stu_id ; select s.stu_id,s.name,s.class_id,c.class_name from stu s , class c where s.class_id =c.class_id(+) union select s.stu_id,s.name,s.class_id,c.class_name from stu s , class c where s.class_id(+) =c.class_id order by stu_id ; --cross jion select s.stu_id,s.name,s.class_id,c.class_name from stu s cross join class c --natural join select stu_id,name ,class_id,c.class_name from stu s natural join class c --补 select stu_id,name ,c.class_name from stu s , class c where s.class_id !=c.class_id