Oracle資料庫之六 單行函式
六、單行函式
6.1、認識單行函式
函式就是和 Java 語言之中的方法的功能是一樣的,都是為了完成某些特定操作的功能支援,而在 Oracle 資料庫裡面也包含了大量的單行函式,這些函式掌握了以後,可以方便的幫助進行資料庫的相關開發。
對開發者而言,最為重要的就是 SQL 語法和單行函式,可是 Oracle 中的單行函式的數量是非常多的。本章只講解使用,後面會講解如何去開發使用者自己的函式(PL/SQL 程式設計)
6.1.1 單行函式語法
funcation_name(列|表示式[,引數1,引數2,])
函式名稱(列 | 表示式 | 數值),而且在Oracle 書中只講解基本的一些單行函式。
6.1.2 單行函式分類
- 字元函式:接收資料返回具體的字元資訊
- 數值函式:對數字進行處理,如:四捨五入
- 日期函式:直接對日期進行相關操作
- 轉換函式:日期、字元、數字之間可以完成互相轉換功能
- 通用函式:Oracle 子句提供的有特色的函式
6.2、字元函式
- 一定是以字元資料為主(字串)
NO. | 函式名稱 | 描述 |
---|---|---|
1 | UPPER(列|字串) | 將字串的內容全部轉大寫 |
2 | LOWER(列|字串) | 將字串的內容全部轉小寫 |
3 | INITCAP(列|字串) | 將字串的開頭首字母大寫 |
4 | REPLACE(列|字串,新的字串) | 使用新的字串替換舊的字串 |
5 | LENGTH(列|字串) | 求出字串長度 |
6 | SUBSTR(列|字串,開始點[,長度]) | 字串擷取 |
7 | ASCII(字元) | 返回與指定字元對應的十進位制數字 |
8 | CHR(數字) | 給出一個整數,並返回與之對應的字元 |
9 | RPAD(列|字串,長度,填充字元) LPAD(列|字串,長度,填充字元) |
在左或右填充指定長度字串 |
10 | LTRIM(字串) , RTRIM(字串) | 去掉左或右空格 |
11 | TRIM(列|字串) | 去掉左右空格 |
12 | INSTR(列|字串,要查詢的字串,開始位置,出現位置) | 查詢一個字串是否在指定位置上出現 |
- 在這裡有一個問題就會出現,在 Oracle 裡面所有的驗證操作必須存在在完整的 SQL 語句之中,所以如果現在只是進行功能驗證,使用的是一張具體的表。
scott 使用者下:
SELECT UPPER('li xing hua')
FORM emp;
- 這個時候發現結果被重複顯示了14行,所以現在函式的功能的確是進行了驗證,但是代價太高。如果使用 DISTINCT 可以消除,那麼如果 emp 表中的資料很多呢?那麼中間處理的資料量就會很大,所以現在就希望有一張表可以幫助使用者進行驗證,而在 Oracle 裡就提供了一個 dual 的資料表(是虛擬表)。
範例:驗證 UPPER() 和 LOWER() 函式
SELECT UPPER('li xing hua'),LOWER('MLDN')
FORM dual;
範例:現在查詢出僱員姓名是“smith”的完整資訊,但是由於失誤,沒有考慮到大小寫問題,此時可以使用UPPER() 函式將全部內容變為大寫。
SELECT *
FORM emp
WHERE ename = UPPER('smith');
範例:查詢所有僱員姓名,要求每個僱員的姓名以首字母大寫的形式出現
SELECT ename 原始姓名,INITCAP(ename) 姓名開頭首字母大寫
FORM emp;
範例:查詢所有僱員資訊,要求將僱員姓名中所有的字母“A”替換成“_”
SELECT ename,REPLACE(ename,'A','_')
FORM emp;
範例:查出姓名長度是5的所有僱員資訊
SELECT *
FORM emp
WHERE LENGTH(ename) = 5;
範例:查詢出僱員姓名前三個字母是“JAM”的僱員資訊
- 那麼現在要想辦法截取出前三個字元,擷取操作就一定要使用 SUBSTR() 函式,要注意的是,SUBSTR() 函式有兩種形式:
- 從指定位置擷取到結尾:SUBSTR(列 | 字串,擷取開始點)
- 擷取部分字串:SUBSTR(列 | 字串,擷取開始點,擷取個數)
SELECT *
FORM emp
WHERE SUBSTR(ename,1,3) = 'JAM';
或者:
SELECT *
FORM emp
WHERE SUBSTR(ename,0,3) = 'JAM';
- 注意:在 Oracle 中,下標都是從1開始,如果設定為0,也會自動將其轉換為1 。
範例: 查詢所有10部門僱員姓名,但不顯示每個僱員姓名的前三個字母
SELECT ename 原姓名,SUBSTR(ename,3) 擷取之後的姓名
FORM emp
WHERE deptno = 10;
範例:顯示每個僱員姓名及姓名的後三個字母
要想擷取每個姓名之中的後三個,首先要解決的問題是開始點,從一個指定的開始點一直擷取到結尾,可是每個僱員的姓名長度是不同的,那麼開始點如何確定呢?
- 實現一:使用傳統做法,先求得姓名長度,然後減2確定開始點
SELECT ename 原始姓名,SUBSTR(ename,LENGTH(ename) - 2) 擷取之後的姓名 FORM emp WHERE deptno = 10;
- 實現二:除了此類做法之外,也可以設定開始點為負數
SELECT ename 原始姓名,SUBSTR(ename,-3) 擷取之後的姓名 FORM emp WHERE deptno = 10;
現在很明顯使用第二種最方便,這個也屬於 Oracle 的特色,不過需要注意的是:Java 語言的字串下標還是從0開始,而且 Java 裡的 substring() 方法是不能設定負數的。
面試題:請問 Oracle 中的 SUBSTR() 函式的下標開始點是從0還是1開始?
答:可以設定為0,也可以設定為1,即使使用了0,那麼最終的結果也會將其定義為1。
範例:返回指定字元的 ASCII 碼
SELECT ASCII('A'),ASCII('L')
FORM dual;
範例:驗證 CHR() 函式,將ASCII 碼變回字元
SELECT CHR(100) FORM dual;
範例:去掉字串左邊空格 - LTRIM() ,去掉右邊空格 - RTRIM()
SELECT ' MLDN LiXingHua ' 原始字串,LTRIM(' ') 去掉左空格
FORM dual;
SELECT ' MLDN LiXingHua ' 原始字串,RTRIM(' ') 去掉右空格
FORM dual;
範例:去掉左右空格
SELECT ' MLDN LiXingHua ' 原始字串,TRIM(' ') 去掉左右空格
FORM dual;
- 不管如何取消空格,中間的空格可是無法消除掉的。
範例:字串左填充 - LPAD() ,字串右填充 - RPAD()
SELECT LPAD('MLDN',10,'*') LPAD函式使用,RPAD('MLDN',10,'*') RPAD函式使用,
LPAD(RPAD('MLDN',10,'*'),16,'*') 組合使用
FORM dual;
範例:字串查詢 - INSTR()
SELECT
INSTR('MLDN Java','MLDN') 查詢得到,
INSTR('MLDN Java','Java') 查詢得到,
INSTR('MLDN Java','JAVA') 查詢不到
FORM dual;
- 這個函式和 Java 中的 indexOf() 方法功能是相同的。
- 小結:
- 字元函式的主要功能是進行字串資料的操作
6.3、數值函式
No. | 函式名稱 | 描述 |
---|---|---|
1 | ROUND(數字[,保留小數]) | 對小數進行四捨五入,可以指定保留位數,如果不指定,則表示將小數點之後的數字全部進行四捨五入 |
2 | TRUNC(數字[,擷取位數]) | 保留指定位數的小數,如果不指定,則表示不保留小數 |
3 | MOD(數字,數字) | 取模 |
範例:驗證 ROUND() 函式的使用
SELECT
ROUND(789.652) 不保留小數,
ROUND(789.652,2) 不保留小數,
ROUND(789.652,-1) 不保留小數,
FROM dual;
範例:列出每個僱員的一些基本資訊和日工資情況
- 對於日工資的計算可以採用30天為基礎,肯定會有小數,就保留2位
SELECT empno,ename,job,hiredate,sal,ROUND(sal/30,2) 日薪金
FROM emp;
- ROUND() 函式的功能是小數進位,而 TRUNC() 的功能是不進位。
範例:驗證 TRUNC() 函式的使用
SELECT
TRUNC(789.652) 擷取小數,
TRUNC(789.652,2) 擷取2位小數,
TRUNC(789.652,-2) 取整
FROM dual;
範例:MOD() 函式驗證,模就是取餘
SELECT MOD(10,3) FROM dual;
6.4、日期函式
- 如果現在要想進行日期的操作,那一定會存在一個前提,必須知道當前日期
- 取得當前的系統時間,可以直接利用 SYSDATE 偽列取得當前日期時間。所謂偽列指的是不是表中的列,但是有可以直接使用的列。
SELECT empno,ename,SYSDATE FROM emp;
SELECT SYSDATE FROM dual;
- 在預設情況下顯示的內容,只包含了年、月、日三個內容,如果要顯示更多內容,就必須修改語言環境。
- 修改日期顯示格式:
- 執行 - sqlplus/nolog - conn c##scott/tiger
- 輸入以下程式碼
ALTER SESSION SET NLS_DATE_FORMAT = 'yyyy-mm-dd hh24:mi:ss';
SELECT SYSDATE FROM dual;
更改的日期顯示格式在關閉視窗重新開啟後就會還原了
- 除了取得系統時間的操作之外,在 Oracle 中也有如下的三個日期操作公式:
- 日期 - 數字 = 日期, 表示若干天前的日期
- 日期 + 數字 = 日期, 表示若干天后的日期
- 日期 - 日期 = 數字(天數),表示兩個日期的天數的間隔
可是絕對不會存在 “日期 + 日期” 的計算,下面為其驗證。
SELECT
SYSDATE+3 三天之後的日期,
SYSDATE-3 三天之前的日期
FROM dual;
範例:查詢出每個僱員的到今天為止的僱傭天數,以及十天前每天僱員的僱傭天數
SELECT empno 僱員編號, ename 僱員姓名,
SYSDATE-hiredate 僱傭天數,
(SYSDATE-10)-hiredate 10天前僱傭天數
FROM emp;
- 結果有小數點,可以用 TRUNC() 擷取小數點
SELECT empno 僱員編號, ename 僱員姓名,
TRUNC(SYSDATE-hiredate) 僱傭天數,
TRUNC((SYSDATE-10)-hiredate) 10天前僱傭天數
FROM emp;
- 以上只是針對於當前時間的操作,對於 Oracle 而言,也提供相應的日期函式,之所以使用日期函式,主要是避免閏年問題,或者是一個月有28,29,30,31天的問題,通過日期函式的計算取得的日期時間是最準確的。
No. | 函式名稱 | 描述 |
---|---|---|
1 | ADD_MONTHS(日期,數字) | 在指定的日期上加入指定的月數,求出新的日期 |
2 | MONTHS_BETWEEN(日期1,日期2) | 求出兩個日期間的僱傭月數 |
3 | NEXT_DAY(日期,星期數) | 求出下一個星期幾的具體日期 |
4 | LAST_DAY(日期) | 求出指定日期所在月的最後一天日期 |
5 | EXTRACT(格式 FROM 資料) | 日期時間分隔,或計算給定兩個日期的間隔 |
範例:驗證 ADD_MONTHS() 函式
- 使用 ADD_MONTHS() 函式的主要功能是在一個指定日期上增加若干個月之後求得的新日期。
SELECT SYSDATE,
ADD_MONTHS(SYSDATE,3) 三個月之後的日期,
ADD_MONTHS(SYSDATE,-3) 三個月之前的日期,
ADD_MONTHS(SYSDATE,60) 六十個月之後的日期,
FROM dual;
範例:要求顯示所有僱員在被僱傭三個月之後的日期
SELECT empno,ename,job,sal,hiredate,ADD_MONTHS(hiredate,3)
FROM emp;
範例:驗證 NEXT_DAY() 函式
- 主要是求出下一個指定的日期數,如果說現在的日期是‘2019年08月30日 星期五’ ,那麼如果現在想要知道下一個‘星期一’ 或是 ‘星期日’ 的具體日期,則可以使用 NEXT_DAY() 函式。
SELECT
SYSDATE,
NEXT_DAY(SYSDATE,'星期日') 下一個星期日,
NEXT_DAY(SYSDATE,'星期一') 下一個星期一
FROM dual;
範例:LAST_DAY() 函式驗證,求當月的最後一天
SELECT SYSDATE,
LAST_DAY(SYSDATE)
FROM dual;
範例:查詢所有是在其僱傭所在月的倒數第三天被公司僱傭的完整僱傭資訊
- 每一位僱員都有自己的僱傭日期,那麼現在要查詢出,你僱傭日期所在月倒數第三天僱傭的人,首先需要知道的是每個僱員僱傭所在月的最後一天。
SELECT empno,ename,job,hiredate,LAST_DAY(hiredate)
FROM emp
WHERE LAST_DAY(hiredate)-2=hiredate;
範例:MONTHS_BETWEEN() 函式的驗證:查詢出每個僱員的編號、姓名、僱員傭日期,僱傭的月數及年份
- MONTHS_BETWEEN() 函式的功能是取得兩個日期時間的月份間隔
SELECT
empno 僱員編號, ename 僱員姓名, hiredate 僱傭日期,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)) 僱傭總月數,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) 僱傭總年數
FROM emp;
範例:查詢出每個僱員的編號、姓名、僱傭日期、已僱傭的年數、月數、天數
- 對於本程式而言,一定是分步計算,而且有一定的難度,因為要操作的是準確性。
- 例如,今天的日期是 2019-09-01日,而 BLAKE 的僱傭日期是 1981-05-01,那麼這位僱員到今天為止被僱傭了38年、4個月、0天。
- 步驟一:求出年,年只需要依靠月就可以計算出來。
SELECT
empno 僱員編號, ename 僱員姓名, hiredate 僱傭日期,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) 僱傭總年數
FROM emp;
- 步驟二:求出月,計算年的時候存在小數,那麼這裡面的資料就是月,只需要求模即可得到。
SELECT
empno 僱員編號, ename 僱員姓名, hiredate 僱傭日期,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) 已僱傭年數,
TRUNC(MOD(MONTHS_BETWEEN(SYSDATE,hiredate),12)) 已僱傭月數
FROM emp;
- 步驟三:是針對於天的計算,因為現在已經計算出了年和月,所以天應該刨去年和月的數字資訊。那麼現在的問題是,如果要想計算天數唯一知道的公式就是 “日期1 - 日期2”,那麼日期1 一定使用的是 SYSDATE ,而日期2(應該去掉年和月),可以利用 ADD_MONTHS() 函式實現此功能。
SELECT
empno 僱員編號, ename 僱員姓名, hiredate 僱傭日期,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) 已僱傭年數,
TRUNC(MOD(MONTHS_BETWEEN(SYSDATE,hiredate),12)) 已僱傭月數,
TRUNC(SYSDATE - ADD_MONTHS(hiredate,MONTHS_BETWEEN(SYSDATE,hiredate))) 已僱傭天數
FROM emp;
範例:EXTRACT() 函式
- 在 Oracle 9i 之後增加了一個 EXTRACT() 函式,此函式的主要功能是可以從一個日期時間(DATE)或者是時間間隔(INTERVAL)中截取出特定的部分,此函式使用語法如下:
EXTRACT
([YEAR | MONTH | DAY | HOUR | MINUTE | SECOND]
| [TIMEZONE_HOUR | TIMEZONE_MINUTE]
| [TIMEZONE_REGION | TIMEZONE_ABBR]
FROM
[日期(date_value) | 時間間隔(interval_value)]);
範例:從日期時間之中取出年、月、日資料
SELECT
EXTRACT(YEAR FROM DATE '2001-09-19') years,
EXTRACT(MONTH FROM DATE '2001-09-19') months,
EXTRACT(DAY FROM DATE '2001-09-19') days
FROM dual;
- 現在是通過一個日期的字串完成,那麼也可以利用當前日期完成。SYSDATE、SYSTIMESTAMP(時間戳)。
SELECT SYSDATE,SYSTIMESTAMP
FROM dual;
範例:從時間戳之中取出年、月、日、時、分、秒
SELECT
EXTRACT(YEAR FROM SYSTIMESTAMP) years,
EXTRACT(MONTH FROM SYSTIMESTAMP) months,
EXTRACT(DAY FROM SYSTIMESTAMP) days,
EXTRACT(HOUR FROM SYSTIMESTAMP) hours,
EXTRACT(MINUTE FROM SYSTIMESTAMP) minutes,
EXTRACT(SECOND FROM SYSTIMESTAMP) seconds
FROM dual;
- 除了以上功能之外,主要功能是取得時間間隔,但是在此處需要使用到一個轉換函式:TO_TIMESTAMP() ,可以將字串變為時間戳,而且此時的內容需要使用到部分子查詢功能,所以此處只為做個演示。
範例:取得兩個日期之間的間隔
SELECT
EXTRACT(DAY FROM TO_TIMESTAMP('1982-08-13 12:17:57','yyyy-mm-dd hh24:mi:ss')
- TO_TIMESTAMP('1981-09-27 09:08:33','yyyy-mm-dd hh24:mi:ss')) days
FROM dual;
範例:取得兩個日期時間之間間隔的天、時、分、秒
SELECT
EXTRACT(DAY FROM datetime_one - datetime_two) days,
EXTRACT(HOUR FROM datetime_one - datetime_two) hours,
EXTRACT(MINUTE FROM datetime_one - datetime_two) minutes,
EXTRACT(SECOND FROM datetime_one - datetime_two) seconds
FROM (
SELECT TO_TIMESTAMP('1982-08-13 12:17:57','yyyy-mm-dd hh24:mi:ss') datetime_one,
TO_TIMESTAMP('1981-09-27 09:08:33','yyyy-mm-dd hh24:mi:ss') datetime_two
FROM dual);
- 如果覺得比較麻煩,也可以不使用子查詢,按原來的方法寫程式碼就如下:
SELECT
EXTRACT(DAY FROM TO_TIMESTAMP('1982-08-13 12:17:57','yyyy-mm-dd hh24:mi:ss')
- TO_TIMESTAMP('1981-09-27 09:08:33','yyyy-mm-dd hh24:mi:ss')) days,
EXTRACT(HOUR FROM TO_TIMESTAMP('1982-08-13 12:17:57','yyyy-mm-dd hh24:mi:ss')
- TO_TIMESTAMP('1981-09-27 09:08:33','yyyy-mm-dd hh24:mi:ss')) hours,
EXTRACT(MINUTE FROM TO_TIMESTAMP('1982-08-13 12:17:57','yyyy-mm-dd hh24:mi:ss')
- TO_TIMESTAMP('1981-09-27 09:08:33','yyyy-mm-dd hh24:mi:ss')) minutes,
EXTRACT(SECOND FROM TO_TIMESTAMP('1982-08-13 12:17:57','yyyy-mm-dd hh24:mi:ss')
- TO_TIMESTAMP('1981-09-27 09:08:33','yyyy-mm-dd hh24:mi:ss')) seconds
FROM dual;
- 這樣看來,第二種方式就是最差的一種方式了,不推薦使用。
6.5、轉換函式
- 在資料庫之中主要使用的資料型別:字元、數字、日期(時間戳),那麼這三種資料型別之間就需要實現轉換操作,這就屬於轉換函式的功能。
No. | 函式名稱 | 描述 |
---|---|---|
1 | TO_CHAR(日期|數字|列, 轉換格式) | 將指定的資料按照指定的格式變為字串型 |
2 | TO_DATE(字串|列, 轉換格式) | 將指定的字串按照指定的格式變為DATE型 |
3 | TO_NUMBER(字串|列) | 將指定的資料型別變為數字型 |
6.5.1 TO_CHAR() 函式
- 在預設的情況下,如果查詢一個日期,則日期預設的顯示格式為“31-1月-12”,而這樣的日期顯示效果肯定不如常見的“2012-01-31” 讓人看起來習慣,所以此時就可以通過TO_CHAR() 函式對這個顯示的日期資料進行格式化(格式化之後的資料是字串),但是如果要完成這種格式化,則首先要熟悉一下格式化日期的替代標記。
日期格式化標記:
No. | 轉換格式 | 描述 |
---|---|---|
1 | YYYY | 完整的年份數字表示,年有四位,所以使用4個Y |
2 | Y,YYY | 帶逗號的年 |
3 | YYY | 年的後三位 |
4 | YY | 年的後兩位 |
5 | Y | 年的最後一位 |
6 | YEAR | 年份的文字表示,直接表示四位的年 |
7 | MONTH | 月份的文字表示,直接表示兩位的月 |
8 | MM | 用兩位數字來表示月份,月有兩位,使用兩個M |
9 | DAY | 天數的文字表示 |
10 | DDD | 表示一年裡的天數(001~366) |
11 | DD | 表示一月裡的天數(01~31) |
12 | D | 表示一週裡的天數(1~7) |
13 | DY | 用文字表示星期幾 |
14 | WW | 表示一年裡的週數 |
15 | W | 表示一月裡的週數 |
16 | HH | 表示12小時制,小時是兩位數字,使用兩個H |
17 | HH24 | 表示24小時制 |
18 | MI | 表示分鐘 |
19 | SS | 表示秒,秒是兩位數字,使用兩個S |
20 | SSSSS | 午夜之後的秒數字表示(0~86399) |
21 | AM|PM (A.M | P.M) | 表示上午或下午 |
22 | FM | 去掉查詢後的前導0,該標記用於時間模板的字尾 |
- 在 TO_CHAR() 函式裡面,需要兩個引數:日期資料,轉換格式
範例:格式化日期時間
SELECT SYSDATE 當前系統時間,
TO_CHAR(SYSDATE,'YYYY-MM-DD') 格式化日期,
TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS') 格式化日期時間,
TO_CHAR(SYSDATE,'FMYYYY-MM-DD HH24:MI:SS') 去掉前導0的時間
FROM dual;
- 注意:在開發中一定別取消前導0
範例:使用其他方式格式化年、月、日
- 除了使用標記(是一種習慣,java.text.SimpleDateFormat),也可以使用單詞表示
SELECT SYSDATE 當前系統時間,
TO_CHAR(SYSDATE,'YEAR-MONTH-DAY') 格式化日期
FROM dual;
或者:
SELECT SYSDATE 當前系統時間,
TO_CHAR(SYSDATE,'YEAR-MONTH-DY') 格式化日期
FROM dual;
範例:查詢出所有在每年2月份僱傭的僱員資訊
SELECT *
FROM emp
WHERE TO_CHAR(hiredate,'MM') = 2;
或者:
SELECT *
FROM emp
WHERE TO_CHAR(hiredate,'MM') = '02';
範例:將每個僱員的僱傭日期進行格式化顯示,要求所有的僱傭日期可以按照“年-月-日”的形式顯示,也可將僱傭的年、月、日拆開分別顯示
SELECT empno,ename,job,hiredate,
TO_CHAR(hiredate,'YYYY-MM-DD') 格式化僱傭日期,
TO_CHAR(hiredate,'YYYY') 年,
TO_CHAR(hiredate,'MM') 月,
TO_CHAR(hiredate,'DD') 日
FROM emp;
- TO_CHAR() 函式的最為重要的功能是可以將數字格式化,例如:2389042809,如果是有經驗的財務人員會按照三位一分:2,389,042,809 ,而要想按照此方法處理數字,就必須格式化。
數字格式化標記
No. | 轉換格式 | 描述 |
---|---|---|
1 | 9 | 表示一位數字 |
2 | 0 | 表示前導0 |
3 | $ | 將貨幣的符號資訊顯示為美元符號 |
4 | L | 根據語言環境不同,自動選擇貨幣符號 |
5 | . | 顯示小數點 |
6 | , | 顯示千位符 |
範例:格式化數字顯示
SELECT
TO_CHAR(987654321.789,'999,999,999,999.9999') 格式化數字,
TO_CHAR(987654321.789,'000,000,000,000.0000') 格式化數字
FROM dual;
- 除了直接對數字格式化,也可以進行貨幣的顯示
SELECT
TO_CHAR(987654321.789,'L999,999,999,999.9999') 顯示貨幣,
TO_CHAR(987654321.789,'$999,999,999,999.9999') 顯示美元
FROM dual;
- 在開發之中,TO_CHAR() 函式的作用還是非常明顯的!建議掌握!
6.5.2 TO_DATE() 函式
- 這個函式主要是將字串變為日期型資料,而改變的過程裡面依然需要之前 TO_CHAR() 函數出現的相關標記。
範例:轉換時間顯示
SELECT
TO_DATE('1979-09-19','YYYY-MM-DD')
FROM dual;
- 在之前講解日期函式時使用了一個 TO_TIMESTAMP() 函式,這個函式是將字串變為時間戳。
範例:時間戳轉換
SELECT
TO_TIMESTAMP('1981-09-27 18:07:10','YYYY-MM-DD HH24:MI:SS') datetime
FROM dual;
6.5.3 TO_NUMBER() 函式
- 作用是將字串變為數字
範例:將字串變為數字
SELECT
TO_NUMBER('09') + TO_NUMBER('19') 加法操作,
TO_NUMBER('09') * TO_NUMBER('19') 乘法操作
FROM dual;
- 但是在之前強調過,Oracle 裡面支援資料型別的自動轉型操作,上面的程式碼也可寫為
SELECT '09' + '19' 加法操作,
'09' * '19' 乘法操作
FROM dual;
6.6、通用函式
- 這些函式是 Oracle 資料庫的特色,對於這些函數了解有一定的好處。
No. | 函式名稱 | 描述 |
---|---|---|
1 | NVL(數字|列 , 預設值) | 如果顯示的數字是null的話,則使用預設數值表示 |
2 | NVL2(數字|列,返回結果一(不為空顯示),返回結果二(為空顯示)) | 判斷指定的列是否是null,如果不為null則返回結果一,為空則返回結果二 |
3 | NULLIF(表示式一,表示式二) | 比較表示式一和表示式二的結果是否相等,如果相等返回NULL,如果不相等返回表示式一 |
4 | DECODE(列|值,判斷值1,顯示結果1,判斷值2,顯示結果2,...,預設值) | 多值判斷,如果某一個列(或一個值)與判斷值相同,則使用指定的顯示結果輸出,如果沒有滿足條件,在顯示預設值 |
5 | CASE 列|數值 WHEN 表示式1 THEN 顯示結果1 ... ELSE 表示式N ... END | 用於實現多條件判斷,在WHEN之後編寫條件,而在THEN之後編寫條件滿足的顯示操作,如果都不滿足則使用ELSE 中的表示式處理 |
6 | COALESCE(表示式1,表示式2,...表示式n) | 將表示式逐個判斷,如果表示式1的內容是null,則顯示錶達式2,如果表示式2的內容是null,則顯示錶達式3,依次類推,如果表示式n的結果還是null,則返回null |
- 對於通用函式而言,只有兩個核心函式:NVL() , DECODE()
6.6.1 使用 NVL() 函式處理 null
- 在資料庫之中,null 是無法進行計算的,即,在一個數學計算之中如果存在了 null,則最後的結果也肯定是 null
範例:查詢出每個僱員的編號、姓名、職位、僱傭日期、年薪
- 對於年薪最準確的做法是應該計算 “sal + comm”,可是這個時候 comm 列上是存在了 null 資料的
SELECT empno,ename,job,hiredate,(sal+comm)*12 年薪,sal,comm
FROM emp;
- 因為 comm 上的內容有的是 null,而現在發現,只要是 comm 為 null 的計算,最終的結果就是 null ,所以在這種情況下需要針對於 null 進行處理,肯定將 null 變為0才合適
範例:驗證 NVL()
SELECT NVL(null,0),NVL(3,0)
FROM dual;
- 這個時候發現如果為 null,那麼就將其變為了0,如果不是 null,就繼續使用指定的數值
SELECT empno,ename,job,hiredate,(sal+NVL(comm,0))*12 年薪,sal,comm
FROM emp;
6.6.2 NVL2() 函式
- NVL2() 函式是在 Oracle 9i 之後增加的一個新的功能函式,相比較 NVL() 函式,NVL2() 函式可以同時對為 null 或不為 null 進行分別判斷並返回不同的結果
範例:查詢每個僱員的編號、姓名、年薪(sal + comm)、基本工資、獎金
SELECT empno,ename,job,hiredate,NVL2(comm,sal+comm,sal),sal,comm
FROM emp;
6.6.3 NULLIF() 函式
- NULLIF(表示式一,表示式二) 函式的主要功能是判斷兩個表示式的結果是否相等,如果相等則返回 NULL ,不相等則返回表示式一
範例:驗證 NULLIF() 函式
SELECT NULLIF(1,1),NULLIF(1,2)
FROM dual;
範例:查詢僱員編號、姓名、職位,比較姓名和職位的長度
SELECT empno,ename,job,LENGTH(ename),LENGTH(job),NULLIF(LENGTH(ename),LENGTH(job)) nullif
FROM emp;
6.6.4 DECODE() 函式
DECODE() 函式是 Oracle 中最有特色的一個函式,DECODE() 函式類似於程式中的 if...else if...else ,但是判斷的內容都是一個具體的值,語法如下:
DECODE(列|表示式, 值1, 輸出結果, 值2, 輸出結果, ..., 預設值)
範例:測試DECODE() 函式
SELECT
DECODE(2,1,'內容為一',2,'內容為二'),
DECODE(2,1,'內容為一','沒有條件滿足')
FROM dual;
範例:現在僱員表中的工作有以下幾種:CLERK:業務員, SALESMAN:銷售人員, MANAGER:經理, ANALYST:分析員, PRESIDENT:總裁 ,要求查詢僱員的姓名、職位、基本工資等資訊,但是要求將所有的職位資訊都替換為中文顯示。
SELECT ename,sal,
DECODE(job,
'CLERK','業務員',
'SALESMAN','銷售人員',
'MANAGER','經理',
'ANALYST','分析員',
'PRESIDENT','總裁') job
FROM emp;
- 但是需要注意的是,如果使用 DECODE() 函式判斷,那麼所有的內容都要判斷,如果只判斷部分內容,其它內容就會顯示 null
6.6.5 CASE 表示式
- CASE 表示式是在 Oracle 9i 引入的,功能與DECODE() 有些類似,都是執行多條件判斷。不過嚴格來講,CASE表示式本身並不屬於一種函式的範疇,它的主要功能是針對於給定的列或者欄位進行依次判斷,在 WHERE 中編寫判斷語句,而在 THEN 中編寫處理語句,最後如果都不滿足則使用 ELSE 進行處理。
範例:顯示每個僱員的工資、姓名、職位,同時顯示新的工資(新的工資標準:辦事員增長10%,銷售人員增長20%,經理增長30%,其他職位的人增長50%)
SELECT ename,sal,
CASE job WHEN 'CLERK' THEN sal * 1.1
WHEN 'SALESMAN' THEN sal * 1.2
WHEN 'MANAGER' THEN sal * 1.3
ELSE sal * 1.5
END 新工資
FROM emp;
6.6.6 COALESCE() 函式
- COALESCE(表示式1, 表示式2, 表示式3,...表示式n) 函式的主要功能是對 null 進行操作,採用依次判斷表示式的方式完成,如果表示式1為 null,則顯示錶達式2的內容,如果表示式2的內容為 null,則顯示錶達式3的內容,依次類推,判斷到最後如果還是null,則最終的顯示結果就是 null 。
範例:驗證 COALESCE() 函式
SELECT ename,sal,comm,COALESCE(comm,100,2000),
COALESCE(comm,null,null)
FROM emp;
- 小結:
- 這些通用函式都具備一些邏輯性的操作在裡面,在以後進行程式編寫時還是會使用到的。
- NVL() 和 DECODE() 是通用函式的基礎,其他函式都在此函式之上進行功能擴充。
說明:本學習資料是根據李興華的Oracle開發實戰經典整