子查詢
單行子查詢和多行子查詢
單行子查詢:子查詢只返回一條記錄
多行子查詢:子查詢返回多條記錄
查詢工資比scott的員工信息
1.scott的工資
2.查詢比3000工資高的員工
注意:
- 括號
- 合理的書寫風格
- 可以在主查詢的where select having from 後面使用子查詢
- 不可以在group by使用子查詢
- 強調from後面的子查詢
- 可以不是一張表,只要子查詢返回的結果 主查詢可以使用即可
- 一般不在子查詢中排序,對主查詢沒有意義,但在top-n分析問題中,必須對子查詢排序
- 子查詢也叫做(內查詢)在主查詢之前一次執行完成, 子查詢的結果被主查詢使用
- 一般先執行子查詢,再執行主查詢,但相關子查詢例外
- 單行子查詢只能使用單行操作符,多行子查詢只能使用多行操作符
- 子查詢中的null值,not in(10,20,null)中,含有null不能使用not in,但是可以使用in
- 原因:單行子查詢中的null值.多行子查詢中的null值.
3.可以在主查詢的where select having from 後面使用子查詢
select empno,ename,sal,(select job from emp where empno=7839) 第四列 from emp
5.強調from後面的子查詢
查詢員工信息:員工號 姓名 月薪
查詢員工信息:員工號 姓名 月薪 年薪
6.可以不是一張表,只要子查詢返回的結果 主查詢可以使用即可
查詢部門名稱市sales的員工
select * from emp where deptno=(select deptno from dept where dname=‘SALES’);
select e.*
from emp e,dept d
where e.deptno=d.deptno and d.dname=‘SALES’;
子查詢在執行的時候是轉換成多表查詢來執行的.
SQL執行計劃
7.單行子查詢只能使用單行操作符,多行子查詢只能使用多行操作符
多行子查詢(重點):
in在集合中
查詢部門名稱是sales和accounting的員工
select * from emp where deptno in(select deptno from dept where dname=‘SALES’ or dname=‘ACCOUNTING’)
select e.* from emp e,dept d where e.deptno=d.deptno and (d.dname=‘SALES’ or d.dname=‘ACCOUNTING’)any:和合集中的任意一個值比較
查詢工資比30號部門任意一個員工高的員工信息
select *
from emp
where sal >any (select sal from emp where deptno=30)查詢工資比30號部門任意一個員工低的員工信息
select *
from emp
where sal <any (select sal from emp where deptno=30)
all:表示我們要和集合中的所有元素比較
查詢工資比30號部門所有員工高的員工信息
select *
from emp
where sal >all(select sal from emp where deptno=30)
select *
from emp
where sal > (select max(sal) from emp where deptno=30);
單行子查詢中的null值問題
查詢是老闆的員工
所有和空值比較的值返回的值都是空值,有空值不要使用not in
查詢所有不是老闆的員工
select *
from emp
where empno not in(select mgr from emp where mgr is not null)
集合運算
注意事項:
- 1.參與運算的各個集合必須列數相同且類型一致
- 2.採用第一個集合作爲最後的表頭
- 3.order by 永遠在最後
- 4.可以使用括號改變順序
SQL的類型
- DML:數據操作語言 select insert update delete
- DDL:數據定義語言 create/drop viewsequence,index,synonym;
- DCL:數據控制語言 grant(授權) revoke(撤銷權限)
insert插入語句
insert into emp (empno,ename,sal,deptno) values(1001.‘TOM’,3000,10);
地址符&:SQL語句中都可以使用
PreparedStatement pst = "insert into emp (empno,ename,sal,deptno)
values(&empno,&ename,&sal,&deptno); "
select empno,ename,sal,&t from emp;
select * from &t;
一次插入多條記錄
一次性將emp中,所有10號部門的員工插入到emp10中
在insert語句中使用子查詢
注意:
不用書寫values子句
子查詢中的值列表應與insert子句中的列明對應
insert into emp10 select * from emp where deptno=10;
海量的插入數據的時候:
1.數據泵(PLSQL程序)
dbms_datapump(程序包)
2.SQL*Loader
3.外部表
update語句中使用子查詢:
數據的完整性:
創建在表中的約束
在oracle中約束的級別?
delete刪除數據:
delete from 表名 where 刪除條件;
如果不加刪除條件的話,就會刪除所有數據
=
Truncate table 表的數據擦除
Truncate與delete的區別
1.delete逐條刪除,Truncate先摧毀表,在重建表
2(重要).delete是DML語句 Truncate是DDL語句
DML(可以回滾) DDL(不可以回滾)
3.delete不會釋放空間,Truncate會
4.delete會產生碎片,Truncate不會
- 去掉碎片:
- alter table<表名> move;
- 數據的導出和導入
- mysql:導出文本文件
- oracle:導出dmp文件 exp imp expdp impdp
5.delete會閃回(flashback),Truncate不可以
delete刪掉 comit之後 發現刪錯了 就可以閃回
flashback其實就是一種恢復
原因:undo數據(還原數據) 這是oracle中非常重要的功能
Oracle中的事務
1.起始標誌:事務中的第一條DML語句(Oracle自動開啓事務)
2.結束標誌:提交:顯式 commit 隱式:正常退出 DDL DCL(創建表,同時提交事務);回滾 顯式 rollback 隱式:非正常推出 掉電 宕機
3.事務之前可以通過savepoint a設置保存點.
rollback to savepoint a 回滾到保存點a
事務的隔離級別:
Oracle支持的3中事務隔離級別:READ COMMITED,SERIALIZABLE,READ ONLY
讀已提交,串行化,只讀 默認爲:讀已提交
mysql的四種隔離級別:
讀未提交數據 | 讀已提交數據 | 可重複讀 | 串行化
課堂練習
找到員工表中工資最高的前三名
ROWNUM僞列,行號
關於行號:
1.rownum永遠按照默認的順序生成(不能用order by)
2.rownum只能使用< <=,不能使用 > >=
select rownum,empno,ename,sal
from (select * from emp order by sal desc)
where rownum<=3
2.rownum只能使用< <=,不能使用 > >=
rownum永遠從1開始
分頁的時候:
select rownum,empno,ename,sal
from (select rownum r,e1.*
from (select * from emp order by sal) e1
where rownum <=8
)
where r >=5;
找到員工表中薪水大於本部門平均工資的員工
select e.deptno,e.empno,e.ename,e.sal,d.avgsal
from emp e,(select deptno,avg(sal) avgsal from emp group by deptno) d
where e.deptno=d.deptno and e.sal > d.avgsal
order by 1
相關子查詢:
將主查詢中的值,作爲參數傳遞給子查詢
一般的子查詢,先執行子查詢在執行主查詢;而相關子查詢,先執行主查詢再執行子查詢
select deptno,empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avgsal
from emp e
where sal > (select avg(sal) from emp where deptno=e.deptno)
order by 1
統計每年入職的員工個數(不許使用子查詢)
select count(*) Total,
sum(decode(to_char(hiredate,‘yyyy’),‘1980’,1,0)) “1980”,
sum(decode(to_char(hiredate,‘yyyy’),‘1981’,1,0)) “1981”,
sum(decode(to_char(hiredate,‘yyyy’),‘1982’,1,0)) “1982”
from emp
行轉列
select deptno,LISTAGG(ename,’,’)within group(order by deptno) nameslist
from emp
group by deptno
使用DDL語句管理表
rowid行地址 僞列
創建表create table emp10 as select * from emp where 1=2;
只創建表結構,不創建數據
創建表:保存20號部門的員工
create table emp20 as select * from emp where deptno=20;
create table empinfo
as
select e.empno,e.ename,e.sal,e.sal12 annsal, d.dname from emp e,dept d
where e.deptno=d.deptno
創建視圖:
create view empinfoview
as
select e.empno,e.ename,e.sal,e.sal12 annsal, d.dname from emp e,dept d
where e.deptno=d.deptno
修改表:
增加一個列
修改現有的列
刪除列
重命名列
重命名錶
drop table刪除表(只是將表放到了oracle的回收站了)
查看回收站 show recyclebin;
清空回收站 purge recyclebin;
直接刪除:drop table test1 purge;
oracle 並不是所有的人都有回收站(管理員沒有回收站)
閃回刪除 flashback table test1 to before drop;
閃回數據歸檔
閃回表
閃回查詢
閃回版本查詢
閃回事務查詢
閃回數據庫
約束的級別:
列級約束 表級約束(聯合主鍵)
檢查性約束:檢查列是否符合某種規則(性別和薪水)
gender varchar2(2) check (gender in (‘男’,‘女’)),
sal number check (sal>0)
因爲主鍵唯一,所以通過主鍵查詢速度最快(其實是通過索引)
外鍵約束
子表的外鍵必須是父表的主鍵
刪除關聯表:
方法一:先刪除子表,再刪除父表
方法二:在父表中將子表的外鍵那一列置空再刪除
方法三:級聯刪除(危險),一般用級聯置空
例子:
create table student(
sid number constraint student_pk primary key,
sname varchar2(20) constraint student_name_notnull not null,
gender varchar2(2) constraint student_gender check (gender in (‘男’,‘女’)),
email varchar2(40) constraint student_email_unique unique
constraint student_email_notnull not null,
deptno number constraint student_fk references dept(deptno) on delete set null
)
注意:創建約束的時候最好起個名字
數據庫對象
表\視圖\序列\索引\同義詞
視圖view
普通用戶沒有權限,需要管理員授權
創建視圖:
create view empinfoview
as
select e.empno,e.ename,e.sal,e.sal*12 annsal, d.dname from emp e,dept d
where e.deptno=d.deptno
視圖是一個虛表(操作跟表基本一樣)
視圖本身不存數據,他是封裝了一條複雜查詢的語句
優點:簡化複雜的查詢
create or replace view empinfoview…(如果存在就替換他)
with read only; (改成只讀)
with check option;(檢查插入)
刪除視圖不會影響表,不建議通過視圖操作表
序列
可供多個用戶用來產生唯一數值的數據庫對象
- 自動提供唯一的數值
- 共享對象
- 主要用於提供主鍵
- 將序列值裝入內存可以提高訪問效率
相當於mysql中的auto_increment
創建序列:
索引
索引是用於加速數據存儲的數據對象.合理的使用索引可以大大降低i/o次數,從而提高數據訪問性能
- 單例索引
- 複合索引
SQL的執行計劃:
explain plan for
同義詞:別名