1. 程式人生 > >Oracle數據庫基本操作(三) —— DQL相關內容說明及應用

Oracle數據庫基本操作(三) —— DQL相關內容說明及應用

保留 group gpo 個數字 轉義字符 ike 關鍵字 其他 單行函數

  本文所使用的查詢表來源於oracle數據中scott用戶中的emp員工表和dept部門表。

一、基本語法

  SQL語句的編寫順序:

select 輸出的列 from 表名 where 條件 group by 分組 having 分組之後的條件過濾 order by 排序;

  1、偽表(dual):Oracle 對語法要求比較嚴格,而偽表/虛表主要用於補齊語法結構,如

select 5+5 from dual;

  2、別名查詢:as關鍵字,但可省略,如:

select ename as 姓名,job 工作 from emp;

  3、去除重復數據:distinct

  註意:若是多列去重,必須是每一列都相同才算重復的。

select distinct job,mgr from emp;

  4、空值問題

  註意:null 值不能參加與SQL四則運算

  null值代表不確定的內容,未知的內容,所有值跟null進行比較,結果都為null。

-- 函數: nvl 若參數1為 null ,則返回參數2, 否則返回參數1

select nvl(null,6) from dual; -- 6

select nvl(5,6) from dual; -- 5

  5、字符串拼接:

    通用 concat(str1,str2) 、Oracle 特有的連接符 ||

select concat(‘abc‘,‘def‘) from dual;

select ‘abc‘||‘def‘||‘xxx‘ from dual;

  6、where條件查詢

    • 關系運算符: > >= = < <= != <>
    • 邏輯運算符: and or not
    • 其它運算符:
      • between..and.. 在區間內
      • in(集合) 在集合內
      • is null
      • is not null
      • like
      • >any(集合) 任意
      • >all(集合) 所有
      • exists(查詢語句)

-- 查詢名字在 ‘ALLEN‘,‘BLAKE‘,‘SCOTT‘ 集合內的員工信息

select * from emp where ename in(‘ALLEN‘,‘BLAKE‘,‘SCOTT‘);

  7、模糊查詢:like

    • % : 匹配任意個數字符
    • _ : 匹配單個字符
    • escape 相當於是指定用哪個字符,作為轉義字符

-- ‘\‘ 不可作為轉義符

select * from emp where ename like ‘%$%%‘ escape ‘$‘;

  8、排序:order by

    • asc : ascend升序 默認
    • desc: descend 降序
    • nulls first | last

select * from emp order by comm asc nulls first;

二、單行函數

  單行函數: 只對一個值進行處理,如字符串函數、數值函數、日期函數等;

 1 -- 數值函數: ceil()向上取整, floor()向下取整, mod()取模, abs()取絕對值, round()四舍五入, trunc()截斷
 2 -- 向上取整
 3 select ceil(-11.9) from dual; -- -11-- round 四舍五入
 4 select round(45.926,2) from dual; -- 45.93
 5 select round(45.926,0) from dual; -- 46
 6 select round(45.926,-1) from dual; -- 50
 7 -- trunc 截斷
 8 select trunc(45.926,2) from dual; -- 45.92
 9 select trunc(55.926,-2) from dual; -- 0
10 
11 -- 字符串函數 
12 -- 輸出每一個員工 : 姓名:ename
13 select concat(姓名:,ename) from emp;
14 -- 長度: length
15 select length(hello) from dual;
16 
17 -- 截取字符串 : 註意: 無論是從0還是1開始,都是從第1個字符開始截取
18 select substr(abcdefg,0,3) from dual; -- abc
19 
20 -- 去除空格
21 select trim(   abc  ) from dual;
22 -- 去除字符串兩端指定的字符   結果: gao qian jing
23 select trim(X from XXXgao qian jingXXXX) from dual;
24 -- 替換
25 select replace(hello,l,x) from dual;
26 
27 -- 日期函數: 查詢當前日期
28 select sysdate from dual; -- 2018/1/31 18:00:03
29 select sysdate+1 from dual; 
30 
31 -- 查詢員工的入職周數
32 select emp.*,(sysdate - hiredate)/7 from emp;
33 -- 查詢員工的入職月數
34 select emp.*,months_between(sysdate,hiredate) from emp;
35 -- 查詢員工的入職年數
36 select emp.*,months_between(sysdate,hiredate)/12 from emp;
37 -- 三個月的優酷會員 , 計算幾個月之後的日期
38 select add_months(sysdate,3) from dual;
39 
40 -- 字符串轉數值: to_number 雞肋
41 select 10 + 24 from dual; -- 34
42 select to_number(10) + 24 from dual;  --34
43 
44 -- 數值轉字符串: 123 對數值進行格式化處理
45 select concat(123,hello) from dual;
46 -- yyyy-mm-dd
47 select emp.*,to_char(sal,$9999.9) from emp;
48 select to_char(1234567,$9,999,999.99) from dual;
49 
50 -- 日期轉字符串
51 select to_char(sysdate,yyyy-mm-dd hh24:mi:ss) from dual;
52 -- 查詢年份
53 select to_char(sysdate,yyyy) from dual;
54 -- 查詢月份
55 select to_char(sysdate,mm) from dual;
56 -- 查詢日數
57 select to_char(sysdate,dd) from dual;
58 select to_char(sysdate,d) from dual; -- 一個星期的第4天
59 select to_char(sysdate,ddd) from dual; -- 一年過了幾天
60 select to_char(sysdate,day) from dual; -- wednesday
61 select to_char(sysdate,dy) from dual;  -- wed
62 
63 -- 字符轉日期
64 select to_date(1980-01-31,yyyy-mm-dd) from dual;
65 
66 -- nvl(p1,p2) 判斷p1是否為null , 若為null, 則返回p2, 否則返回p1
67 -- nvl2(p1,p2,p3) 類似三元運算符
68 select nvl2(null,5,6) from dual; --6
69 select nvl2(1,5,6) from dual; --5

  條件表達式: 

通用寫法:

case 列

when 值1 then 輸出

when 值2 then 輸出

when 值3 then 輸出

else

      

end;

Oracle特有的寫法:

decode(列名,if1,then1,if2,then2,default)

  條件表達式使用示例:

 1 -- 給員工表所有的員工取一個中文名稱
 2 select ename,case ename
 3                  when SMI%TH then 曹賊
 4                  when ALLEN then 劉備小兒  
 5                  when MARTIN then 諸葛村夫
 6                  else
 7                    路人甲
 8                  end              
 9 from emp;
10 ------------------------------
11 select ename,
12        decode(ename,SMI%TH,曹賊,ALLEN,劉備小兒,路人乙)
13 from emp;
14 -------------------------------
15 select emp.*,case 
16                 when sal<1500 then 貧農
17                 when sal>=1500 and sal<=3000 then 中農 
18                 else
19                       地主
20                 end 階級    
21 from emp;

三、多行函數

  1、多行/聚合函數: count,max ,min ,avg ,sum
  註意: 聚合函數在執行運算的過程中會忽略空值
1 -- 查詢所有員工人數
2 select count(*) from emp;
3 
4 -- 查詢獎金總金額 2200
5 select sum(comm) from emp;
6 
7 -- 查詢全公司平均獎金 550
8 select avg(comm) from emp;
9 select sum(comm)/count(*) from emp;

  2、分組查詢

  select 分組的條件,分組之後的操作 from 表名 group by 分組條件 having 分組之後的條件過濾

  本質: 先對表中數據按照分組的條件進行排序,然後再執行分組之後的運算

  註意: 分組查詢時: select後面只能輸出分組的條件和分組之後的操作
1 -- 查詢每個部門的平均工資
2 select deptno,avg(sal) from emp group by deptno;
3 
4 -- 查詢每個部門的平均工資,並且平均高於2000
5 select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;

  3、where 和 having區別

  • where 是在分組之前執行的條件過濾, 不能接聚合函數, 可以接單行函數
  • having 是分組之後的條件過略,可以接聚合函數

四、多表查詢

1、內連接查詢

 1 -- 同時查詢兩張表,多表查詢, 
 2 -- 查詢出的結果為笛卡爾積:表示的是兩張表的乘積,結果沒有實際意義
 3 select * from emp,dept;
 4 
 5 -- 在笛卡爾積的基礎上篩選出有意義的數據
 6 -- 隱式內連接
 7 select * from emp e,dept d where e.deptno = d.deptno;
 8 
 9 -- 顯式內連接: inner join..on..
10 select * from emp e inner join dept d on e.deptno = d.deptno;
11 
12 -- 隱式內連接查詢示例
13 -- 查詢員工編號,員工姓名,員工的部門名稱,工資等級, 經理編號,經理姓名,經理的部門名稱,經理的工資等級
14 select e.empno, e.ename,d1.dname,
15        case s1.grade
16          when 1 then 一級
17            when 2 then 二級
18              when 3 then 三級
19                when 4 then 四級
20                  when 5 then 五級
21                    end 工資等級,
22        e.mgr, m.ename,d2.dname,
23        case s2.grade
24          when 1 then 一級
25            when 2 then 二級
26              when 3 then 三級
27                when 4 then 四級
28                  when 5 then 五級
29                    end 工資等級
30 from emp e, emp m,dept d1,dept d2,salgrade s1,salgrade s2
31 where e.mgr = m.empno
32        and e.deptno = d1.deptno
33        and m.deptno = d2.deptno
34        and e.sal between s1.losal and s1.hisal
35        and m.sal between s2.losal and s2.hisal;

2、外連接查詢

標準/通用的寫法:
左外連接: 以左表為基礎,查詢左表中所有的記錄以及左表和右表對應的記錄,若右表沒有對應的記錄,則顯示null
left outer join..on..
  右外連接:以右表為基礎,查詢右表中所有的記錄以及左表和右表對應的記錄,若左表沒有對應的記錄,則顯示null
right outer join..on..
  Oracle外連接特有的寫法:
(+) : 若沒有對應的記錄,則添加null顯示
 1 -- 左外連接
 2 select * from emp e left outer join dept d on e.deptno = d.deptno;
 3 -- 使用Oracle特有寫法,查詢左外連接的結果
 4 select * from emp e,dept d where e.deptno = d.deptno(+);
 5 
 6 -- 右外連接
 7 select * from emp e right outer join dept d on e.deptno = d.deptno;
 8 -- 使用Oracle特有寫法,查詢右外連接的結果
 9 select * from emp e,dept d where e.deptno(+) = d.deptno;
10 
11 -- 擴展: 全外連接  full outer join
12 select * from emp e full outer join dept d on e.deptno=d.deptno;

五、子查詢 

子查詢: 一個查詢語句中嵌套另一個查詢內容

作用: 解決復雜的查詢需求

1、單行子查詢:子查詢出來的結果只有單個值

  操作符: > >= = < <= != <>

1 -- 查詢最高工資的員工信息
2 select * from emp where sal = (select max(sal) from emp);
3 -- 查詢出比 雇員7654的工資 高,同時 和7788從事相同工作 的員工信息
4 select * from emp where sal > (select sal from emp where empno=7654) and job = (select job from emp where empno=7788);

2、多行子查詢:子查詢出來的結果有多行

 操作符: in any all exists
1 -- 查詢所有是領導的員工信息
2 select * from emp where empno =any(select distinct mgr from emp)
3 -- 查詢所有不是領導的員工信息
4 -- 註意:子查詢中的空值問題
5 select * from emp where empno not in(select distinct mgr from emp where mgr is not null);
6 select * from emp where empno != all(select distinct mgr from emp where mgr is not null);
  exists(查詢語句):存在的意思
    • 若查詢語句存在結果,則返回true
    • 若查詢語句不存在結果,則返回false
1 -- 當條件滿足時相當於 1=1,不滿足時相當於1=2
2 select * from emp where exists(select * from dept where deptno=10);
3 select * from emp where 1=1;
4 
5 select * from emp where exists(select * from dept where deptno=100);
6 select * from emp where 1=2;

六、SQL編寫順序與執行順序

  • SQL編寫順序
select..from..where..group by..having..order by..
  • SQL執行順序:
from..where..group by..having..select..order by..

  先從表中獲取數據,判斷是否符合條件,對符合條件的數據就進行分組,分組完後,在組內進行判斷是否符合指定條件,篩選出符合條件的數據,根據選擇要求進一步篩選出需要的字段,並將所有數據根據規則進行排序。

  • 關聯子查詢與非關聯子查詢執行順序

技術分享圖片

七、偽列(oracle特有)

1、rownum : 偽列/虛列, 表示的行號,主要運用在Oralce分頁查詢中,借助子查詢
     每查詢出一條滿足條件的記錄,數據庫中默認已經存在rownum,起始值是從1開始的,每輸出一條記錄,rownum++;
 1 -- 查詢rownum >5 的所有記錄,由於沒有輸出任何記錄,所以rownum並不會自動增長,條件永遠不符合,查詢出的結果為null
 2 select rownum,emp.* from emp where rownum > 5;
 3 -- 查詢rownum <5 的所有記錄,此語句正常輸出
 4 select rownum,emp.* from emp where rownum < 5;
 5 
 6 -- 查詢員工表中工資最高的前三名的員工信息
 7 select rownum, empno, ename, sal
 8   from (select emp.* from emp order by sal desc) t
 9  where rownum <= 3;
10 -- 查詢員工表中第5-10的記錄
11 -- 先查詢前10條記錄,查詢line >=5 的所有記錄
12 select *
13      from (select rownum line, emp.* from emp where rownum <= 10) t
14 where line >= 5;

2、rowid : 偽列, 表示的每行記錄在磁盤中存放的物理地址, 主要是運用在索引查詢中。

select rowid,emp.* from emp where deptno=20;

技術分享圖片

  當要刪除表中重復記錄時,可根據指定字段進行分組,查詢所有最小rowid,只保留rowid最小的記錄,刪除掉其他記錄即可。

八、集合運算

  並集運算: union

  應用場景:

  數據統計的時候

1997年,公司開發項目記錄員工信息

    員工編號, 員工姓名, 年齡, 工資, 大哥大

2007年,系統升級,QQ,手機

  新的員工表:

    員工編號, 員工姓名, 昵稱 年齡, 工資,QQ,手機

SQL語句示例:

 1 -- 查詢工資大於1500, 或者是20號部門下的員工
 2 select * from emp where sal > 1500 or deptno = 20;
 3 
 4 -- 並集運算: 去除重復記錄
 5 select * from emp where sal > 1500
 6 union
 7 select * from emp where deptno=20;
 8 
 9 -- 並集運算:不去重
10 select * from emp where sal > 1500
11 union all
12 select * from emp where deptno=20;
13 
14 -- 交集運算
15 select * from emp where sal > 1500
16 intersect
17 select * from emp where deptno=20;
18 
19 -- 差集運算
20 select * from emp where sal > 1500
21 minus
22 select * from emp where deptno=20;

技術分享圖片

集合運算中的註意事項:

1. 結果集列的數量必須保持一致, 可以使用相同類型或者null補齊

2. 列的類型要保持一致

3. 集合運算的時, 列的含義要相同或者接近

 1 select ename,sal from emp where sal > 1500
 2 union
 3 select ename,sal from emp where deptno=20;
 4 
 5 select ename,sal from emp where sal > 1500
 6 union
 7 select ename,0 from emp where deptno=20;
 8 
 9 select ename,sal from emp where sal > 1500
10 union
11 select ename,null from emp where deptno=20;
12 
13 -- 錯誤的演示
14 select ename,sal from emp where sal > 1500
15 union
16 select ename,沒有 from emp where deptno=20;
17 
18 select ename,sal from emp where sal > 1500
19 union

Oracle數據庫基本操作(三) —— DQL相關內容說明及應用