1. 程式人生 > >關係查詢(Oracle)

關係查詢(Oracle)

什麼叫子查詢?

子查詢也叫巢狀查詢,是指嵌入在其他sql語句中的select語句。

單行子查詢

單行子查詢是指只返回一條記錄的子查詢語句。

查詢工資最高的人的資訊

select * from emp where sal = (select max(sal) from emp);

顯示部門平均工資低於2000的部門的員工資訊

select * from emp where deptno in (select deptno from emp group by deptno having avg(sal)<2000);

多行子查詢

多行子查詢是指返回多行資料的子查詢。

查詢和部門10 工作相同的僱員的名字,崗位,工資,部門號

  1. 先查詢部門10有哪些崗位。

select distinct(job) from emp where deptno=10;

  1. 顯示這些崗位的員工

select * from emp where job in (select distinct(job) from emp where deptno=10);

在子查詢中使用all操作符  [熟悉]

顯示工資比部門30所有員工的工資都高的員工姓名    【要大於所有】

select * from emp where sal > all(select sal from emp where deptno=30);

在子查詢中使用any操作符 [熟悉]

顯示工資比部門30任意員工的工資都高的員工姓名   【只要大於一個】

select * from emp where sal > any(select sal from emp where deptno=30);

多列子查詢

查詢和SCOTT部門和崗位完全相同的所有僱員。

思路1:

使用兩個子查詢分別查詢

select * from emp where deptno = (select deptno from emp where ename='SCOTT') and job = (select job from emp where ename='SCOTT');

思路2:

使用括號   oracle特有的,其他資料庫不一定支援。

select * from emp where (deptno,job)= (select deptno,job from emp where ename='SCOTT');

使用子查詢建立新表

寫法:create 新表名 as select from 舊錶名

create table empbak as select * from emp where 1=0;--建立空表

create table empbak2(id,name,sal) as select empno,ename,sal from emp;--建立有內容表

使用子查詢自我複製資料

寫法:insert into 新表名[列名] select [*,列名] from舊錶。

insert into empbak(empno,ename,job,mgr,hiredate,sal,comm,deptno) select * from emp;

insert into empbak(empno,ename) select * from emp;--錯誤寫法,值過多

insert into empbak(empno,ename) select empno,ename from emp;

合併查詢

union  用於取得兩個結果集的並集,自動去掉重複的行

select * from emp union select * from emp;--14條記錄

union all 將兩個結果集相加,不會去掉重複的行

select * from emp union all select * from emp;--28條記錄

intersect  取交集,自動去掉重複的行

select * from emp where sal>800 intersect select * from emp where sal>2000;

minus  取差集,自動去掉重複的行

select * from emp where sal>800 minus select * from emp where sal>2000;

--不同表  取出相同型別的列  也可以使用   建議使用別名

select empno idno,ename idname from emp union select deptno idno,dname idname from dept;

select empno ,ename  from emp union select deptno ,dname  from dept;

笛卡爾集   交叉連線  【熟悉cross join】

在多表查詢的時候,如果不帶任何條件,則會出現笛卡爾集。

select * from emp;--14條記錄

select * from dept;--4條記錄

select * from emp,dept;--56條記錄  隱式交叉連線

select * from emp cross join dept;--顯示交叉連線

select * from salgrade;--5條記錄

select * from dept,emp,salgrade;--280條記錄

select * from dept cross join emp cross join salgrade;

笛卡爾集出現原理:

從dept中取出一條記錄,分別於emp中的每一條記錄匹配。

直到dept中的所有記錄於emp中的所有記錄全部匹配。

怎樣避免笛卡爾集?

多表查詢的條件至少不能少於表的個數-1.

等值連線

一個使用者查詢請求涉及到多個表的時候,連線多個表的條件為=時,就是等值連線查詢。

在實際開發中,我們不可避免的需要對兩張或是兩張以上的表進行聯合查詢,比如顯示僱員名字,僱員工資以及所在部門的名字。

--普通寫法

select emp.ename,emp.sal,dept.dname from dept ,emp where dept.deptno = emp.deptno;

--正確寫法  【不建議】

select ename,sal,dname from dept ,emp where dept.deptno = emp.deptno;

--錯誤寫法,未明確定義列

select ename,sal,dname,deptno from dept ,emp where dept.deptno = emp.deptno;

--使用別名 [推薦寫法]

select t2.ename,t2.sal,t1.dname from dept t1,emp t2 where t1.deptno = t2.deptno;

顯示部門號為10的部門名,員工名和工資

select t1.ename,t1.sal,t2.dname from emp t1, dept t2 where t1.deptno=t2.deptno and t1.deptno=10;

非等值連線

一個使用者查詢請求涉及到多個表的時候,連線多個表的條件不是=時,就是非等值連線查詢;

查詢工資級別為1的員工資訊。

select * from emp t1,salgrade t2 where t2.grade=1 and t1.sal between t2.losal and t2.hisal;

顯示各個員工的姓名,工資以及工資級別。

select emp.ename,emp.sal,salgrade.grade from emp,salgrade where emp.sal between salgrade.losal and salgrade.hisal;

自然連線  【熟悉】

自然連線是通過對參與表關係中所有同名的屬性對取等(即相等比較)來完成的,故無須自己新增連線條件

select * from emp natural join dept;--有同名列場景

select * from emp,dept where emp.deptno = dept.deptno;--效果等價

select * from emp natural join salgrade;--如果沒有同名列 生成笛卡爾集

using連線  【熟悉】

相比較natural 更加靈活,可以指定多個列。

需要使用()   ()內可以有多個列,但必須是兩者都有的列,使用逗號分隔。

select * from emp join dept using (deptno);

select * from emp,dept where emp.deptno = dept.deptno;--效果等價

on連線   【熟悉】

相比較using更加靈活,可以指定不同列名。

select * from emp join dept on emp.deptno = dept.deptno;

自連線

顯示員工JONES的上級領導的姓名

select * from emp where empno = ( select mgr from emp where ename = 'JONES');

顯示所有員工和他上級的姓名?

思路 把emp看成兩張表。(worker,manager)

select worker.ename,manager.ename from emp worker,emp manager where worker.mgr = manager.empno;

疑惑?

只顯示了13條記錄,KING沒有顯示,因為他沒有上級。

Oracle的連線分類【瞭解】

oracle的連線分為內連線和外連線。

什麼叫內連線?

內連線實際上就是利用where子句對兩張表形成的笛卡爾集進行篩選。是開發中用的最多的連線查詢,前面部分我們學習的都是內連線。

基本語法:

select  列名1,…… from 表1 inner join 表2 on 查詢條件;

效果等同於select 列名1,…… from 表1,表2 where 查詢條件;

外連線

外連線分成左外聯,右外聯,完全外聯。

外連線 左連線

如果左表的記錄不能和右表記錄進行關聯也要展示。

場景:有學生5名,其中3名學生缺席考試。

create table stu(id number,name varchar2(20));

create table exam(id number,grade number);

insert into stu values(1,'小明');

insert into stu values(2,'張三');

insert into stu values(3,'李四');

insert into stu values(4,'王五');

insert into stu values(5,'趙六');

insert into exam values(1,90);

insert into exam values(2,100);

select * from stu,exam where stu.id = exam.id;--沒有參加考試的學生將不能顯示

select * from stu left join exam on stu.id = exam.id;--沒有參加考試的學生可以顯示

select * from stu,exam where stu.id = exam.id(+);--另外的寫法

外連線 右連線

如果右表的記錄不能和左表關聯也要展示

場景:有插班生進行考試,插班生id在學生資訊表中沒有。

insert into exam values(12,100);

select * from stu right join exam on stu.id = exam.id; --顯示插班生考試成績

select * from stu,exam where stu.id(+) = exam.id;--另一種寫法

select * from exam left join stu on stu.id = exam.id;--此種寫法跟表名順序相關,左右連互轉

select * from stu,exam where exam.id = stu.id(+);--此種寫法與表名的順序無關,跟欄位相關

外連線 完全外聯

不管是否有匹配記錄,都顯示出來。

select * from stu full outer join exam on stu.id = exam.id;

select * from stu full join exam on stu.id = exam.id;

三表連線

查詢員工的員工資訊,部門名稱,工資級別

select t1.*,t2.dname,t3.grade from emp t1,dept t2,salgrade t3

where t1.deptno = t2.deptno

and t1.sal between t3.losal and t3.hisal;