多表查询
select * from emp,dept;
对产生笛卡尔积效果,消除笛卡尔积要使用关联字段
select * from emp,dept where emp.deptno=dept.deptno
虽然笛卡尔积都不显示,但是笛卡尔积仍然存在,所以笛卡尔积多表查询性能会很差。
范例:查询每个雇员的编号、姓名、职位、基本工资、部门名称、部门位置信息
select emp.empno,emp.ename,emp.job,emp.sal,dept.dname,dept.loc
from emp,dept
where emp.deptno=dept.deptno;
tips:给表命名别名,可以让程序读写简单
select e.empno,e.ename,e.job,e.sal,d.dname,d.loc
from emp e,dept d
where e.deptno=d.deptno;
查找雇员的编号,姓名,工资,工资等级
select e.empno,e.ename,e.sal,s.grade
from emp e,salgrade s
where e.sal between s.losal and hisal;
上例将工资等级格式化为:“A等工资”
select e.empno,e.ename,e.sal,
decode(s.grade,1,'E工资等级',
2,'D工资等级',
3,'C工资等级',
4,'B工资等级',
5,'A工资等级')as grade
from emp e,salgrade s
where e.sal between s.losal and s.hisal;
查询出每个雇员的姓名、职位、基本工资、部门名称、工资所在的工资等级(三个表两两连接)
如果存在多个消除笛卡尔积的条件,通常使用and将这些条件连接在一起
select e.ename,e.job,e.sal,d.dname,decode(s.grade,1,'E工资等级',
2,'D工资等级',
3,'C工资等级',
4,'B工资等级',
5,'A工资等级')as grade
from emp e,dept d,salgrade s
where e.deptno=d.deptno and e.sal between s.losal and s.hisal;
外连接
对于数据库表的连接操作在数据库之中一共定义了两种:
内连接:也称为等值连接(连接、普通连接、自然连接),是最早的一种连接方式,
内连接是从结果中删除与其他连接表中没有匹配行的所有元组,所以当匹配条件不满足是内连接
可能会丢失信息。在之前所使用的连接方式都属于内连接,而在where子句之中设置消除笛卡尔积
的条件就采用了等值判断的方式进行的。
外链接:内连接中只能够显示等值满足的条件,如果不满足的条件则无法显示,如果现在希望特定
表中的数据可以全部显示,就利用外链接,外链接分为三种:左外连接(左连接)、右外连接(右连接)
全外连接(全连接)。
insert into emp (empno,ename,job,mgr,hiredate,sal,comm)
values(8888,'dgq','manager',7839,sysdate,8000,2000);
select *
from emp e,dept d
where e.deptno=d.deptno;
左外连接:左关系属性=右关系属性(+)
右外连接:左关系属性(+)=右关系属性
左外连接:(显示等式左边表里未显示完整的数据)
select *
from emp e,dept d
where e.deptno=d.deptno(+);
右外连接:(显示等式右边表里未显示完整的数据)
select *
from emp e,dept d
where e.deptno(+)=d.deptno;
自身连接:
查询雇员的编号姓名,以及雇员领导的编号和姓名
select e1.empno,e1.ename,e2.empno,e2.ename
from emp e1,emp e2
where e1.mgr=e2.empno(+);
范例:注意分析步骤。
查询出在1981年雇佣的全部雇员的编号、姓名、雇佣日期(按照年-月-日显示)、工作、领导姓名
雇员月工资、雇员年工资(基本工资+奖金)雇员的工资等级、部门编号、部门名称、部门位置,并且
要求这些雇员的月基本工资在1500-3500之间,将最后的结果按照年工资的降序排列,如果年工资相等
,则按照工作进行排列。
分析步骤:1.确定所需要的数据表,
emp表1:编号、姓名、雇佣日期、工作、月工资
emp表2:领导姓名
dept表:部门编号、名称、位置
salgrade表:工资等级
2.确定已知的相关字段:
雇员和领导:emp1.mgr=emp2.empno
雇员和部门:emp.deptno=dept.deptno
雇员和工资等级:emp.sal between salgrade.losal and salgrade.hisal
select e1.empno,e1.ename,e1.hiredate,e1.job,e1.sal,(e1.sal+nvl(e1.comm,0))*12 as 年薪,
e1.ename,d.deptno,d.dname,d.loc,s.grade
from emp e1,emp e2,dept d,salgrade s
where to_char(e1.hiredate, 'yyyy')=1981 and
e1.sal between 1500 and 3500 and
e1.mgr=e2.empno(+) and e1.deptno=d.deptno(+)
and e1.sal between s.losal and s.hisal
order by 年薪 desc,e1.job ;
(注:select 在orderby之前执行,所以排序可以用已经定义过的列)
SQL1999语法
交叉连接(cross join)作用于两个关系上,并且第一个关系的每个元组与第二个关系的所有元组进行连接,
这样的操作形式与笛卡尔积是完全相同的,交叉连接的语法如下:
select * from table1 表别名1,[cross join table2 表别名2]where...
交叉连接主要功能就是产生笛卡尔积,没有其他功能
select * from emp cross join dept;
一般而言,在进行多表连接的时候都一定会存在关联字段一消除笛卡尔积。例如deptno字段,就可以
利用自然连接来消除掉笛卡尔积。
自然连接
自然连接(natural join)运算作用于两个关系,最终会通过两个关系产生出一个关系作为结果。
与交叉连接不同的是自然连接只考虑那些在两个关系模式中都出现的属性上取值相同的元组对。
select * from emp natural join dept;
这个时候会把连接的字段放在第一列上进行显示,而且这种方式就是一种内连接的方式。
using 子句
通过自然连接可以直接使用关联字段消除笛卡尔积,如果两张表中没有存在这种关联字段的话,
就可以通过using子句完成笛卡尔积的消除。
select * from emp join dept using(deptno);
on子句
在SQL:1999语法中通过on子句就可以由用户手工设置一个关联条件,消除笛卡尔积。
using子句是设置连接字段,而on是设置连接条件的。
select * from emp e join salgrade s on(e.sal between s.losal and s.hisal);
外连接
在数据的查询操作中数据的外连接一共分为三种形式:左外连接、右外连接、全外连接。
语法连接如下:
select 列 from 表1 表名1 [left|right|full outer join 表2 on(关联条件)]
[where条件]
[order by 排序字段1 asc|desc,排序字段2];
对于外连接,在之前使用的是(+),这个标记只能实现左外连接或者右外连接,但是对于全外连接无法实现
这是只能使用SQL:1999语法之中规定的内容。全外连接的使用情况并不多。个人建议,如果使用的是oracle
数据库,就使用(+)标记控制左右外连接,不使用它实现内连接。
范例:实现右外连接
select * from emp e right outer join dept d on e.deptno=d.deptno;
左外连接:
select * from emp e left outer join dept d on e.deptno=d.deptno;
全外连接
select * from emp e full outer join dept d on e.deptno=d.deptno;