1. 程式人生 > >ORACLE 常用sql用法和及註意事項

ORACLE 常用sql用法和及註意事項

com 從右到左 指定 turn 但是 數據 lba etime its

1.exits和in用法

1)說明:

  1. exists對外表做循環,每次循環對內表查詢;in將內表和外表做hash連接

  2. 使用exists oracle會先檢查主查詢; 使用in,首先執行子查詢,並將結果存儲在臨時表中

2)使用:

  表class和student表

  技術分享圖片 技術分享圖片

  下面查詢student中classno在class中的數據

  1. 使用exists和not exists

select name, classno from student where exists (select * from class where student.classno= class.classno);

  結果:

  技術分享圖片

select name, classno from student where not exists (select * from class where student.classno= class.classno);

  結果:

  技術分享圖片

select name, classno  from student where classno  in (select classno from class);

  2. 使用in 和not in

select name, classno  from student where classno not in (select classno from class);

  技術分享圖片

  結果:

  技術分享圖片

3)比較

  1. 如果兩個表大小相當,in和exists差別不大

  2. 如果兩個表大小相差較大則子查詢表大的用exists,子查詢表小的用in

  3.盡量不要使用not in

 

2.union和union all

1)說明:

  1. 使用場景:需要將兩個select語句結果整體顯示時,可以使用union和union all

  2. union對兩個結果集取並集不包含重復結果同時進行默認規則的排序;而union all對兩個結果集去並集,包括重復行,不進行排序

  3. union需要進行重復值掃描,效率低,如果沒有要刪除重復行,應該使用union all

  4. insersect和minus分別交集和差集,都不包括重復行,並且進行默認規則的排序

2)使用註意事項

  1.可以將多個結果集合並

  2. 必須保證select集合的結果有相同個數的列,並且每個列的類型是一樣的(列名不一定要相同,會默認將第一個結果的列名作為結果集的列名)

3)例子:

表student

技術分享圖片

eg1:

select name, score from student where score> 60
union all 
select name, score from student where score <200;

結果:(有重復,沒有排序)

技術分享圖片

select name, score from student where score> 60
union
select name, score from student where score <200;

結果:(沒有重復,並且排序了)

技術分享圖片

3.with as

1)說明:

  1. with table as 可以建立臨時表,一次分析,多次使用

  2. 對於復雜查詢,使用with table as可以抽取公共查詢部分,多次查詢時可以提高效率

  3. 增強了易讀性

2)語法:

with tabName as (select ...)

3)例子:

表student

技術分享圖片

eg1:

select rownum, name, score from (select rownum, name,score from student where score >70 order by score); 

可以更換成:

with table_s as (select rownum, name,score from student where score >70 order by score)
select name, score from table_s;

結果:

技術分享圖片

4)多個with table as 一起使用時用逗號隔開,並且只能使用一個with如下例子

eg1:

with vt1 as (select * from student where score >=60),
vt2 as (select * from class),
vt3 as (select * from teacher)
select vt1.name, vt1.score, vt2.classname, vt3.teachername  from vt1,vt2,vt3 where vt1.classno= vt2.classno and vt1.teacherid=vt3.teacherid;

eg2:

技術分享圖片
with vt as (select t.* 
from travelrecord t where t.starttime>=to_date(2014-02-01‘,yyyy-mm-dd‘) and t.endtime<=to_date(2014-04-30‘,yyyy-mm-dd‘)+1 and to_char(starttime,hh24‘)>=08and to_char(endtime,hh24‘)<=11and t.vehiclenum=100088110000),
vt1 as (select  sum(vt4.traveltime) as stoptime from ((select * from vt where vt.state=0)vt4)),
vt2 as (select sum(vt.traveltime)as "ONLINETIME1",sum(vt.distance)as "DISTANCE1"from vt)
select vt1.stoptime,vt2.distance1, vt2.onlinetime1 from vt2, vt1;
技術分享圖片

4. order by

1)說明:

  1. order by 決定oracle如何將查詢結果排序

  2. 不指定asc或者desc時默認asc

2)使用:

  1. 單列升序(可以去掉asc)

select * from student order by score asc;

  2. 多列升序

select * from student order by score,  deptno;

技術分享圖片

  3. 多列降序

select * from student order by score desc,  deptno  desc;

  4. 混合

select * from student order by score asc,  deptno  desc;

3)對NULL的處理

  1. oracle在order by 時認為null是最大值,asc時排在最後,desc時排在最前

  eg:

select * from student order by score asc;

結果:
技術分享圖片

  2. 使用nulls first (不管asc或者desc,null記錄排在最前)或者nulls last 可以控制null的位置,eg:

select * from student order by score asc nulls first;

結果如下:

技術分享圖片

4)將某行數據置頂(decode)

  eg1:

select * from student order by decode(score,100,1,2);

結果:

技術分享圖片

eg2: (某一行置頂,其他的升序)

select * from student order by decode(score,100,1,2), score;

技術分享圖片

5)註意事項

  1. 任何在order by 語句的非索引項都將降低查詢速度

  2. 避免在order by 子句中使用表達式

5. group by

1)說明:

  1.用於對where執行結果進行分組

2)簡單例子:

eg1:

技術分享圖片

select sum(score), deptno from student group by deptno;

結果:

技術分享圖片

eg2:

select deptno,sum(score) from student where deptno>1  group by deptno;

結果:

技術分享圖片

6.where和having

1)說明:

  1. where和having都是用來篩選數據,但是執行的順序不同 where --group by--having(即分組計算前計算where語句,分組計算後計算having‘語句),詳情查看章節一sql執行順序

  2. having一般用來對分組後的數據進行篩選

  3. where中不能使用聚組函數如sum,count,max等

2)例子:

eg1: 對 5 中group by 的數據篩選

select deptno,sum(score) from student where deptno>1  group by deptno having sum(score)>100;

結果:

技術分享圖片

7. case when 和decode

1)說明:

  1. decode更簡潔

  2. decode只能做等值的條件區分,case when可以使用區間的做判斷

2)語法:

技術分享圖片
decode(條件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值)

--等價於:

IF 條件=值1 THEN
    RETURN(翻譯值1)
ELSIF 條件=值2 THEN
    RETURN(翻譯值2)
    ......
ELSIF 條件=值n THEN
    RETURN(翻譯值n)
ELSE
    RETURN(缺省值)
END IF
技術分享圖片

CASE expr WHEN comparison_expr1 THEN return_expr1
         [WHEN comparison_expr2 THEN return_expr2
          WHEN comparison_exprn THEN return_exprn
          ELSE else_expr]
END

技術分享圖片
CASE
         WHEN comparison_expr1 THEN return_expr1
         [WHEN comparison_expr2 THEN return_expr2
          WHEN comparison_exprn THEN return_exprn
          ELSE else_expr]
END
技術分享圖片

3)例子:

eg1:

方式一:

技術分享圖片
select name, score,gender,
  case gender when 1then when 2then else 未說明end gender_t
from student;
技術分享圖片

方式二:

技術分享圖片
select name, score,gender,
  case  when gender=1then when  gender=2then else 未說明end gender_t
from student;
技術分享圖片

方式三:

select name,gender,decode(gender,1‘,‘,2‘,‘,未說明‘)gender_t from student;

結果:

技術分享圖片

eg2:

技術分享圖片
select name,score, 
    case  when score >80 then優秀when score>=60 and score <=80 then 良好when score<60 then 不及格end  evalution
from student; 
技術分享圖片

結果:

技術分享圖片

設置默認值,將null置為沒成績:

技術分享圖片
select name,score, 
    case  when score >80 then優秀when score>=60 and score <=80 then 良好when score<60 then 不及格else 沒成績end  evalution
from student; 
技術分享圖片

結果:

技術分享圖片

4)註意:

  1.case有兩種形式,其中case 表達式 when then方式效率高於case when 表達式效率

  2.使用decode函數可以避免重復掃描相同記錄或者重復連接相同的表,因而某些情況可以減少處理時間

SQL 優化總結

1. SQL優化一般性原則

  1)目標:減少服務器資源消耗(主要是磁盤IO)

  2)設計:

    1. 盡量依賴oracle優化器

    2. 合適的索引(數據重復量大的列不要簡歷二叉樹索引,可以使用位圖索引; 對應數據操作頻繁的表,索引需要定期重建,減少失效的索引和碎片)

  3)編碼:

    1.利用索引

    2. 合理利用臨時表

    3. 避免寫過於復雜的sql;

    4. 盡量減小事務的粒度

2. 具體註意事項

  1)查詢時盡量使用確定的列名

  2)盡量少使用嵌套的子查詢,這種查詢很消耗cpu資源

  3)多表查詢的時候,選擇最有效率的表名順序

   oracle解析器對表的處理順序從右到左,所以記錄少的表放在右邊(最右邊的表為基礎表,drivering table最先被處理), 如果3個以上的表連接查詢,則要選擇交叉表作為基礎表

  4)or比較多時分為多個查詢,使用union all(盡量用union all代替union)聯結(適應於索引列)

    詳細見上一章節union和union all

  5) 盡量多用commit提交事務,可以及時釋放資源、解鎖、釋放日誌

  6)訪問頻繁的表可以放置在內存中

  7)避免復雜的多表關聯

  8)避免distinct,union(並集),minus(差集),intersect(交集),order by等耗費資源的操作,因為會執行耗費資源的排序功能

  9)使用exists替代distinct

ORACLE 常用sql用法和及註意事項