Oracle_SQL(5) 連接和子查詢
一、連接join
一般分類:
inner join: 內連接,又叫等值連接,只返回兩個表中連接字段相等的行。
left join :左連接,返回左表中所有的記錄以及右表中連接字段相等的記錄。
right join :右連接,返回右表中所有的記錄以及左表中連接字段相等的記錄。
full join:外連接,返回兩個表中的行:left join + right join。
cross join:笛卡爾積,就是第一個表的行數乘以第二個表的行數。
oracle分類:等值連接 =
外連接(左外連接、右外連接、全連接)=(+)
笛卡爾積
update emp set deptno=null where empno=7839;
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno;
select emp.*,dept.*
from emp inner join dept on emp.deptno=dept.deptno;
2.左連接\左外連接
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+);
select emp.*,dept.*
from emp left join dept on emp.deptno=dept.deptno;
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno;
select emp.*,dept.*
from emp right join dept on emp.deptno=dept.deptno;
4.外連接\全連接
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+)
union
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno;
select emp.*,dept.*
from emp full join dept on emp.deptno=dept.deptno;
5.笛卡爾積
select emp.*,dept.* from emp,dept;
select emp.*,dept.* from emp cross join dept;
二、子查詢
在查詢語句的select、from、where部分再嵌入一個查詢語句,
這個被嵌入的查詢語句稱為子查詢。
子查詢可以被多層嵌套。
1.select子查詢
select emp.*,
(select dname from dept where dept.deptno=emp.deptno) as dname
from emp;
2.from子查詢
select emp.*,dept1.* from emp,
(select * from dept where dname in (‘RESEARCH‘,‘SALES‘)) dept1
where dept1.deptno=emp.deptno;
3.where子查詢
select emp.* from emp where emp.deptno in
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
select emp.* from emp where exists
(select 1 from dept where dept.deptno=emp.deptno
and dname in (‘RESEARCH‘,‘SALES‘));
4.對應的連接查詢
select emp.*,dept.* from emp,dept
where dept.deptno=emp.deptno and dname in (‘RESEARCH‘,‘SALES‘);
5.總結:一般連接查詢效率是最高,但受到數據質量的限制比較多,
且不容易寫出sql或sql的健壯性不足。
比如:要查出所有職員的部門名稱,用連接查詢時需要考慮每個職員是否有部門編號,
如果都有部門編號時,可以用等值連接書寫;
如果存在沒有部門編號的職員時,就要考慮用外連接,至於時左外連接還是右外連接還和職員表與部門表的位置有關;
這就增加的書寫sql的難度,並增加的錯誤出現的概率。
用select子查詢示例的方式書寫就不用考慮這些問題,簡化的編寫sql的難度,
且不用考慮數據的真實情況。
但如果要查詢的字段比較多時,select子查詢示例的方式又比較低效,
所以需要綜合考慮。
在結果正確的前提下考慮sql程序的健壯性、效率。
三、謂詞查詢
0.in 某列的值屬於集合成員中的一個成員
select emp.* from emp where emp.deptno in
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
1.exists 總存在一個值滿足條件
select emp.* from emp where exists
(select 1 from dept where dept.deptno=emp.deptno
and dname in (‘RESEARCH‘,‘SALES‘));
2.not exists 不存在任何值滿足條件
select emp.* from emp where not exists
(select 1 from dept where dept.deptno=emp.deptno
and dname in (‘RESEARCH‘,‘SALES‘));
3.any 某列的值滿足一個條件即可
select emp.* from emp where emp.deptno = any
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
4.some 滿足集合中的某些值
select emp.* from emp where emp.deptno = some
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
5.all 某列的值滿足子查詢中所有值的記錄
select emp.* from emp where emp.deptno = all
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
select * from emp where emp.deptno <
all(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
6.總結:
exists、any、some與in的功能是類似的,not exists、all與not in功能類似;
any、some、all比起in來不方便理解,基本不在實際中使用;
exists和not exists要比in和not in效率高,所以需要重點掌握。
如果對exists和not exists理解有困難的話,
可以先用in和not in寫出sql,在按照格式修改為exists和not exists即可。
四、查詢結果的並、交、差
1.union 並(去重)
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+)
union
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno;
2.union all 並(不去重)
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+)
union all
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno;
3.intersect 交
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+)
intersect
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno;
等價與等值連接
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno;
4.minus 差
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+)
minus
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno;
差操作的結果的兩個查詢的位置有關:
select emp.*,dept.* from emp,dept where emp.deptno(+)=dept.deptno
minus
select emp.*,dept.* from emp,dept where emp.deptno=dept.deptno(+);
五、子查詢對增刪改功能的增強
1.批量新增
語法:insert into <表名> (列名,...) 子查詢;
insert into dept
(select empno/100 as deptno,ename as dname,ename as loc
from emp where job=‘MANAGER‘);
2.批量修改
語法:update <表名> set <列名1>=<表達式1>,... where 子查詢;
update emp set sal=sal+500 where deptno in
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
3.批量刪除
語法:delete from <表名> where 子查詢;
delete from emp where emp.deptno in
(select deptno from dept where dname in (‘RESEARCH‘,‘SALES‘));
Oracle_SQL(5) 連接和子查詢