1. 程式人生 > >Oracle_子查詢和常用函式

Oracle_子查詢和常用函式

1、子查詢

子查詢在 SELECT、UPDATE、DELETE 語句內部可以出現 SELECT 語句。內部的 SELECT 語句結果可以作為外部語句中條件子句的一部分,也可以作為外部查詢的臨時表。子查詢的型別有:

  1. 單行子查詢:不向外部返回結果,或者只返回一行結果。
  2. 多行子查詢:向外部返回零行、一行或者多行結果。

案例 1:查詢出銷售部(SALES)下面的員工姓名,工作,工資。
案例分析:該問題可以用聯接查詢實現,由於所需的結果資訊都在 Emp 表中,可以先從 Dept 表中查詢出銷售部對應的部門號,然後根據當前部門號再到 Emp 表中查詢出符合該部門的員工記錄即可。從銷售表中查詢出的結果可以作為 Emp 表中查詢的條件,SQL 語句實現如下:

程式碼解析:
內部查詢的結果作為外部查詢的條件。需要注意:如果內部查詢不返回任何記錄,則外部條件中欄位 DEPTNO 與 NULL 比較永遠為假,也就是說外部查詢不返還任何結果。

  • 在單行子查詢中外部查詢可以使用=、>、<、>=、<=、<>等比較運算子。
  • 內部查詢返回的結果必須與外部查詢條件中的欄位(DEPTNO)匹配。
  • 如果內部查詢返回多行結果則出現錯誤。

案例 2:查詢出 Emp 表中比任意一個銷售員(“SALESMAN”)工資低的員工姓名、工作、工資。
案例分析:銷售員在 Emp 表中有很多條記錄,每個人工資不相等,如果返回“比任意員工的工資還低”的條件,返回比“最高工資還低”即可。如果用子查詢做,子查詢中就會返回多條記錄。用普通的關係符(>、<等)執行就會出錯。這時候需要用關鍵字 ANY。ANY 放在比較運算子後面,表示“任意”的意思。

程式碼演示:ANY 子查詢

程式碼解析:
<any:比子查詢結果中任意的值都小,也就是說,比子查詢結果中最大值還小,那麼同理>any 表示比子查詢結果中最小的還大。

案例 3:查詢出比所有銷售員的工資都高的員工姓名,工作,工資。

案例分析:ANY 可以表示任意的,但本案例中要求比所有銷售員工資都高,那麼就要使用另外一個關鍵字 ALL。ALL 與關係操作符一起使用,表示與子查詢中所有元素比較。

程式碼解析:

  • >ALL:比子查詢結果中所有值還要大,也就是說,比子查詢結果中最大值還要大。
  • <ALL 表示比最小值還要小。

對於子查詢還可以使用 IN 和 NOT IN 操作符進行操作。

2、Oracle 中的偽列

在 Oracle 的表的使用過程中,實際表中還有一些附加的列,稱為偽列。偽列就像表中的列一樣,但是在表中並不儲存。偽列只能查詢,不能進行增刪改操作。接下來學習兩個偽列:ROWID 和 ROWNUM。

(1) ROWID

表中的每一行在資料檔案中都有一個實體地址,ROWID 偽列返回的就是該行的實體地址。使用 ROWID 可以快速的定位表中的某一行。ROWID 值可以唯一的標識表中的一行。由於 ROWID 返回的是該行的實體地址,因此使用 ROWID 可以顯示行是如何儲存的。

程式碼演示:ROWID

(2) ROWNUM

在查詢的結果集中,ROWNUM 為結果集中每一行標識一個行號,第一行返回 1,第二行返回 2,以此類推。通過 ROWNUM 偽列可以限制查詢結果集中返回的行數。

PS:ROWNUM 與 ROWID 不同,ROWID 是插入記錄時生成,ROWNUM 是查詢資料時生成。ROWID 標識的是行的實體地址。ROWNUM 標識的是查詢結果中的行的次序。

案例 4:查詢出員工表中前 5 名員工的姓名,工作,工資。

程式碼演示:ROWNUM

案例 5:查詢出工資最高的前 5 名員工的姓名、工資和工資。
案例分析:“工資最高的前 5 名”需要先降序排序,再取前 5 名,但是生成 ROWNUM 操作比排序要早,排序時已經連同 ROWNUM 一起排序了,因此不能直接在案例 1 的語句中直接加上Order by 就行,而是需要對排序的結果重新做二次查詢,產生新的 ROWNUM 才能作為查詢的條件依據。

程式碼演示:ROWNUM 應用

案例 6:查詢出表 EMP 中第 5 條到第 10 條之間的記錄。
案例分析:這是分頁的應用。在查詢條件中,如果查詢條件中 ROWNUM 大於某一正整數,則不返還任何結果。

程式碼演示:ROWNUM 分頁

3、 Oracle 函式

Oracle SQL 提供了用於執行特定操作的專用函式。這些函式大大增強了 SQL 語言的功能。函式可以接受零個或者多個輸入引數,並返回一個輸出結果。Oracle 資料庫中主要使用兩種型別的函式:

  1. 單行函式:對每一個函式應用在表的記錄中時,只能輸入一行結果,返回一個結果,比如:MOD(x,y)返回 x 除以 y 的餘數(x 和 y 可以是兩個整數,也可以是表中的整數列)。常用的單行函式有:
  2. 聚合函式:聚合函式同時可以對多行資料進行操作,並返回一個結果。比如 SUM(x)返回結果集中 x 列的總合。
  • 字元函式:對字串操作。
  • 數字函式:對數字進行計算,返回一個數字。
  • 轉換函式:可以將一種資料型別轉換為另外一種資料型別。
  • 日期函式:對日期和時間進行處理。

(1)字元函式

 字元函式接受字元引數,這些引數可以是表中的列,也可以是一個字串表示式。下表列出了常用的字元函式。

函式 說明
ASCII(x) 返回字元 x 的 ASCII 碼。
CONCAT(x,y) 連線字串 x 和 y。
INSTR(x, str [,start] [,n) 在 x 中查詢 str,可以指定從 start 開始,也可以指定從第 n 次開始。
LENGTH(x) 返回 x 的長度。
LOWER(x) x 轉換為小寫。
UPPER(x) x 轉換為大寫。
LTRIM(x[,trim_str]) 把 x 的左邊截去 trim_str 字串,預設截去空格。
RTRIM(x[,trim_str]) 把 x 的右邊截去 trim_str 字串,預設截去空格。
TRIM([trim_str FROM] x) 把 x 的兩邊截去 trim_str 字串,預設截去空格。
REPLACE(x,old,new) 在 x 中查詢 old,並替換為 new。
SUBSTR(x,start[,length]) 返回 x 的字串,從 staart 處開始,擷取 length 個字元,預設 length,預設到結尾。
SQL> SELECT ASCII('a') FROM DUAL;

ASCII('A')
----------
        97

SQL> SELECT CONCAT('Hello', ' world') FROM DUAL;

CONCAT('HEL
-----------
Hello world

SQL>SELECT INSTR('Hello world','or') FROM DUAL;           

INSTR('HELLOWORLD','OR')
------------------------
                       8

SQL> SELECT LENGTH('Hello') FROM DUAL;

LENGTH('HELLO')
---------------
              5

SQL> SELECT LOWER('hElLO') FROM DUAL;

LOWER
-----
hello

SQL> SELECT UPPER('hello') FROM DUAL;

UPPER
-----
HELLO

SQL> SELECT LTRIM('===HELLO===', '=') FROM DUAL;

LTRIM('=
--------
HELLO===

SQL> SELECT '=='||LTRIM('    HELLO===') FROM DUAL;

'=='||LTRI
----------
==HELLO===

SQL> SELECT RTRIM('===HELLO===', '=') FROM DUAL;

RTRIM('=
--------
===HELLO

SQL> SELECT '='||TRIM('    HELLO    ')||'=' FROM DUAL;

'='||TR
-------
=HELLO=

SQL> SELECT TRIM('=' FROM '===HELLO===') FROM DUAL;

TRIM(
-----
HELLO

SQL> SELECT REPLACE('ABCDE','CD','AAA') FROM DUAL;

REPLAC
------
ABAAAE

SQL> SELECT SUBSTR('ABCDE',2) FROM DUAL;

SUBS
----
BCDE

SQL> SELECT SUBSTR('ABCDE',2,3) FROM DUAL;

SUB
---
BCD

(2)數字函式

數字函式接受數字引數,引數可以來自表中的一列,也可以是一個數字表達式。

函式 說明 示例
ABS(x) x 絕對值 ABS(-3)=3
ACOS(x) x 的反餘弦 ACOS(1)=0
COS(x) 餘弦 COS(1)=1.57079633
CEIL(x) 大於或等於 x 的最小值 CEIL(5.4)=6
FLOOR(x) 小於或等於 x 的最大值 FLOOR(5.8)=5
LOG(x,y) x 為底 y 的對數 LOG(2,4)=2
MOD(x,y) x 除以 y 的餘數 MOD(8,3)=2
POWER(x,y) x 的 y 次冪 POWER(2,3)=8
ROUND(x[,y]) x 在第 y 位四捨五入 ROUND(3.456,2)=3.46
SQRT(x) x 的平方根 SQRT(4)=2
TRUNC(x[,y]) x 在第 y 位截斷 TRUNC(3.456,2)=3.45

說明:

1、ROUND(X[,Y]),四捨五入。

        在預設 y 時,預設 y=0;比如:ROUND(3.56)=4。
        y 是正整數,就是四捨五入到小數點後 y 位。ROUND(5.654,2)=5.65。
        y 是負整數,四捨五入到小數點左邊|y|位。ROUND(351.654,-2)=400。

2、TRUNC(x[,y]),直接擷取,不四捨五入。

       在預設 y 時,預設 y=0;比如:TRUNC (3.56)=3。
       y 是正整數,就是四捨五入到小數點後 y 位。TRUNC (5.654,2)=5.65。
       y 是負整數,四捨五入到小數點左邊|y|位。TRUNC (351.654,-2)=300。

(3)日期函式

日期函式對日期進行運算。常用的日期函式有:

   1.ADD_MONTHS(d,n),在某一個日期 d 上,加上指定的月數 n,返回計算後的新日期。d 表示日期,n 表示要加的月數。

    2.LAST_DAY(d),返回指定日期當月的最後一天。

   3.ROUND(d[,fmt]),返回一個以 fmt 為格式的四捨五入日期值,d 是日期,fmt 是格式模型。預設 fmt 為 DDD,即月中的某一天。

  • 如果 fmt 為“YEAR”則舍入到某年的 1 月 1 日,即前半年捨去,後半年作為下一年。
  • 如果 fmt 為“MONTH”則舍入到某月的 1 日,即前月捨去,後半月作為下一月。
  • 預設為“DDD”,即月中的某一天,最靠近的天,前半天捨去,後半天作為第二天。
  • 如果 fmt 為“DAY”則舍入到最近的周的週日,即上半周捨去,下半周作為下一週週日。

與 ROUND 對應的函式時 TRUNC(d[,fmt])對日期的操作,TRUNC 與 ROUND 非常相似,只是不對日期進行舍入,直接擷取到對應格式的第一天。

   4. EXTRACT(fmt FROM d),提取日期中的特定部分。

fmt 為:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND。其中 YEAR、MONTH、DAY可以為 DATE 型別匹配,也可以與 TIMESTAMP 型別匹配;但是 HOUR、MINUTE、SECOND 必須與 TIMESTAMP 型別匹配。HOUR 匹配的結果中沒有加上時區,因此在中國執行的結果小 8 小時。

(4)轉換函式
轉換函式將值從一種資料型別轉換為另外一種資料型別。常用的轉換函式有:

    1. TO_CHAR(d|n[,fmt])。 把日期和數字轉換為制定格式的字串。

程式碼演示:TO_CHAR 對日期的處理

程式碼解析:
在格式化字串中,使用雙引號對非格式化字元進行引用。針對數字的格式化,格式化字元有:

引數 示例 說明
9 999 指定位置處顯示數字。
* 9.9 指定位置返回小數點
99,99 指定位置返回一個逗號
$ $999 數字開頭返回一個美元符號
EEEE 9.99EEEE 科學計數法表示
L L999 數字前加一個本地貨幣符號
PR 999PR 如果數字式負數則用尖括號進行表示

程式碼演示:TO_CHAR 對數字的處理

    2. TO_DATE(x [,fmt])  把一個字串以 fmt 格式轉換為一個日期型別

    3. TO_NUMBER(x[,fmt])   把一個字串以 fmt 格式轉換為一個數字。

程式碼演示:TO_NUM 函式

(4)其他單行函式

    1.  NVL(x,value)  如果 x 為空,返回 value,否則返回 x。

案例 7:對工資是 2000 元以下的員工,如果沒有發獎金,每人獎金 100 元。

程式碼演示:NVL 函式

    2.  NVL2(x,value1,value2)  如果 x 非空,返回 value1,否則返回 value2。

案例 8:對 EMP 表中工資為 2000 元以下的員工,如果沒有獎金,則獎金為 200 元,如果有獎金,則在原來的獎金基礎上加 100 元。

程式碼演示:NVL2 函式

(5)聚合函式

聚合函式同時對一組資料進行操作,返回一行結果,比如計算一組資料的總和,平均值等。

名稱 作用 語法
AVG 平均值 AVG(表示式)
SUM 求和 SUM(表示式)
MIN、MAX 最小值、最大值 MIN(表示式)、MAX(表示式)
COUNT 資料統計 COUNT(表示式)

案例 9:求本月所有員工的基本工資總和。

程式碼演示:SUM 函式

案例 10:求不同部門的平均工資。

程式碼演示:AVG 函式下的分組查詢