<b>Oracle 10g資料庫基礎之基本查詢語句-中-函數</b>
--資料參考:張烈 張建中《資料庫管理者教育訓練講義》
<b>函數:</b>
使用函數的目的是為了操作資料
将輸入的變量處理,傳回一個結果。
變量可以有好多。
傳入的變量可以是列的值,也可以是表達式。
函數可以嵌套。
内層函數的結果是外層函數的變量。
單行函數:每一行都有一個傳回值,但可以有多個變量。
多行函數:多行有一個傳回值。
<b>單行函數的分類:</b>
字元操作函數
數字操作函數
日期操作函數
資料類型轉換函數
綜合資料類型函數
<b>字元操作函數:</b>
<b>大小寫操作函數</b>
<b>Lower,upper,initcap </b><b>小寫</b><b>大寫</b><b>首字母大寫</b>
<b>字元串操作函數</b>
<b>Concat,length,substr,instr,trim,replace,lpad,rpad</b>
<b>實驗12:操作字元串的函數</b>
大小寫操作函數
Lower,upper,initcap 小寫大寫首字母大寫
字元串操作函數
Concat,length,substr,instr,trim,replace,lpad,rpad
該實驗的目的是掌握常用的字元串操作的函數.
字元串的大小寫操作
SQL> Select lower(ename),upper(ename),initcap(ename) from emp;
SQL>Select lower(ename) 小寫字母,upper(ename) 大寫字母,initcap(ename) 首字母大寫 from emp;
<a href="http://blog.51cto.com/attachment/201205/203032223.png" target="_blank"></a>
SQL> select lower(' mf TR') 小寫字母, upper('mf TR') 大寫字母, initcap('mf TR') 首字母大寫 from dual;
Dual是虛表,讓我們用表的形式來通路函數的值。
<a href="http://blog.51cto.com/attachment/201205/203043497.png" target="_blank"></a>
其它字元串操作函數
<b>concat</b><b>将兩個字元連接配接到一起</b>
select ename,job,concat(ename,job) from emp;
<a href="http://blog.51cto.com/attachment/201205/203112227.png" target="_blank"></a>
<b>求字元串的長度</b>
下面三句話是求字元串的長度,字元串要單引。
select length('張三') from dual;--按照字
select lengthb('張三') from dual;--按位元組
select lengthc('張三') from dual;--unicode的長度
<a href="http://blog.51cto.com/attachment/201205/203139283.png" target="_blank"></a>
<b>substr</b><b>截取字元串</b>
substr(字元串,m,n),m是從第幾個字元開始,如果為負的意思是從後邊的第幾個開始。N是數多少個,如果不說就是一直到字元串的結尾
SQL> select ename,substr(ename,1,1) "第一個字母",substr(ename,-2) "最後兩個字母"from emp;
<a href="http://blog.51cto.com/attachment/201205/203159728.png" target="_blank"></a>
<b>求子串在父串中的位置</b>,0表示沒有在父串中找到該子串。
SQL> select ename,instr(ename,'A') "A在第幾位" from emp;
<a href="http://blog.51cto.com/attachment/201205/203236460.png" target="_blank"></a>
<b>trim</b><b>截斷字元串和添加字元串的函數</b>
<b>Trim</b><b>函數是截掉頭或者尾連續的字元,一般我們的用途是去掉空格。</b>
SQL> select trim(leading 'a' from 'aaabababaaa') from dual;
<b>截掉連續的前置的</b><b>a</b>
<a href="http://blog.51cto.com/attachment/201205/203256110.png" target="_blank"></a>
SQL> select trim(trailing 'a' from 'aaabababaaa') from dual;
<b>截掉連續的後置的</b><b>a</b>
<a href="http://blog.51cto.com/attachment/201205/203400543.png" target="_blank"></a>
SQL> select trim(both 'a' from 'aaabababaaa') from dual;
<b>截掉連續的前置和後置的</b><b>a</b>
<a href="http://blog.51cto.com/attachment/201205/203413424.png" target="_blank"></a>
SQL> select trim('a' from 'aaabababaaa') from dual;
<b>如果不說明是前置還是後置就是</b><b>both</b><b>全截斷。</b>
<a href="http://blog.51cto.com/attachment/201205/203434299.png" target="_blank"></a>
<b>Lpad</b><b>和</b><b>rpad</b><b>字元填充</b>
SQL> select lpad(ename,20,'*') ename,rpad(ename,20,'。') ename from emp;
<b>左填充和右填充,</b><b>20</b><b>是總共填充到多少位,</b><b>*</b><b>和。是要填充的字元串。</b>
<b>Lpad</b><b>左填充,</b><b>rpad</b><b>右填充,一般的用途是美化輸出的結果。</b>
<b>如果位數不足,按照截取後的結果顯示,不報錯。</b>
select lpad(sal,18,'*')左填充18位星号,rpad(sal,25,'。')右填充25位句号,sal from emp;
<a href="http://blog.51cto.com/attachment/201205/203559534.png" target="_blank"></a>
select lpad(sal,30,' ')左填充30位空格,rpad(sal,30,' ')右填充30位空格,sal from emp;
<a href="http://blog.51cto.com/attachment/201205/203613539.png" target="_blank"></a>
<b>REPLACE</b><b>替換字元</b>
SQL> SELECT REPLACE('JACK and JUE','J','xj_') FROM DUAL;
<b>将字元串中的</b><b>J</b><b>全部替換位</b><b>xj_</b>
<a href="http://blog.51cto.com/attachment/201205/203628583.png" target="_blank"></a>
<b>實驗13:操作數字的函數</b>
該實驗的目的是掌握常用的關于數字操作的函數.
<b> ROUND</b><b>,</b><b>TRUNC</b><b>數字操作函數</b>
以小數點位核心,2是小數點後兩位,0可以不寫,表示取整,-1表示小數點前一位
<b>ROUND</b><b>是四舍五入:</b>
<b>SQL> SELECT ROUND(45.923,2), ROUND(45.923,0), ROUND(45.923,-1) FROM DUAL;</b>
<a href="http://blog.51cto.com/attachment/201205/203714921.png" target="_blank"></a>
<b>TRUNC</b><b>是截斷,全部舍棄:</b>
<b>SQL> SELECT TRUNC(45.923,2), TRUNC(45.923), TRUNC(45.923,-2) FROM DUAL;</b>
<a href="http://blog.51cto.com/attachment/201205/203726720.png" target="_blank"></a>
<b>ceil</b><b>取整,上進位,和</b><b>trunc</b><b>全部去掉正好相反</b>
<b>SQL> select ceil(45.001) from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/203738312.png" target="_blank"></a>
<b>取絕對值</b>
<b>SQL> select abs(-23.00) from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/203749330.png" target="_blank"></a>
<b>取餘數</b>
<b>SQL> select mod(8.88,2) from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/203800996.png" target="_blank"></a>
<b>實驗14:操作日期的函數</b>
該實驗的目的是掌握常用的關于日期操作的函數.
<b>系統日期的操作</b>
日期是很特殊的資料類型,用好了可以提高資料庫的性能,而使用不當往往是錯誤的根源,如果你使用字元型資料來存儲日期,就放棄日期特有的計算功能。
<b>函數</b><b>SYSDATE</b><b>求目前資料庫的時間。</b>
SQL> select sysdate from dual;
日期的顯示格式和用戶端的配置相關。
<a href="http://blog.51cto.com/attachment/201205/203955836.png" target="_blank"></a>
<b>檢視目前的日期顯示格式</b>
SQL> select * from nls_session_parameters
where parameter='NLS_DATE_FORMAT';
<a href="http://blog.51cto.com/attachment/201205/204019352.png" target="_blank"></a>
col value for a20
代表的含義是凡是列的名稱是value的,都按照20個寬度來顯示,你想取消該列的定義
col value clear,其中col是column的縮寫。你想檢視幫助help column即可
alter session set NLS_DATE_FORMAT='yyyy/mm/dd:hh24:mi:ss';
重新設定為我們想要的格式。
select sysdate from dual;
SYSDATE
-------------------
2012/5/16007/05/01:16:32:54
檢視系統時間,資料庫本身沒有時間,它有scn号,和我們的時間不同。
alter session set NLS_DATE_FORMAT='DD-MON-RR';
設定為預設的顯示格式
再次檢視,我們發現日期的顯示随着用戶端的格式變化而變化。
日期的内部存儲都是以yyyymmddhh24miss存在資料庫中
<b>日期的操作函數</b>
SQL> select round(sysdate-hiredate) days,sysdate,hiredate from emp;
<a href="http://blog.51cto.com/attachment/201205/204032706.png" target="_blank"></a>
兩個日期相減的結果機關為天,往往是帶小數點。我們通過函數可以取整。
<b>取兩個日期的月間隔</b>
<b>SQL> select months_between(sysdate,hiredate) 兩個日期的月間隔,sysdate,hiredate from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204044922.png" target="_blank"></a>
<b>六個月過後是哪天</b><b>?</b>
<b>SQL> select sysdate </b><b>今天</b><b>, add_months(sysdate,6) </b><b>六個月後</b><b> from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/204151229.png" target="_blank"></a>
<b>SQL> select next_day(hiredate,5) ,hiredate from emp;</b>
<b>目前的日期算起,下一個星期五是哪一天,</b>這句話你可能運作失敗,因為日期和用戶端的字元集設定有關系,如果你是英文的用戶端,就的用Friday來表達,日期是格式和字元集敏感的。如果你是中文的用戶端,就的用‘星期五’來表達。
<a href="http://blog.51cto.com/attachment/201205/204204453.png" target="_blank"></a>
<b>該日期的月底是哪一天。</b>
<a href="http://blog.51cto.com/attachment/201205/204213786.png" target="_blank"></a>
<b>日期的進位和截取</b>
select hiredate,round(hiredate,'mm') ,round(hiredate,'month') from emp;
select hiredate,round(hiredate,'yyyy') ,round(hiredate,'year') from emp;
select hiredate,trunc(hiredate,'mm') ,trunc(hiredate,'month') from emp;
select hiredate,trunc(hiredate,'yyyy') ,trunc(hiredate,'year') from emp;
數字的進位和截取是以小數點為中心,我們取小數點前或後的值,而日期的進位和截取是以年,月,日,時,分,秒為中心。
<b>資料類型的隐式轉換</b>
字元串可以轉化為數字和日期。
數字要合法,日期要格式比對。
select ename,empno from emp where empno='7900';
數字和日期在指派的時候也可以轉為字元串,但在表達式的時候不可以轉換。
select ename,empno from emp where ename='123';
select ename,empno from emp where ename=123;
<b>資料類型的顯式轉換</b>
To_char,to_date,to_number
<b>日期轉化為字元串,請說明字元串的格式。</b>
<b>SQL> select ename,to_char(hiredate,'yyyy/mm/dd') from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204347906.png" target="_blank"></a>
<b>FM</b><b>消除前置的零和空格。</b>
<b>SQL> select ename,to_char(hiredate,'fmyyyy/mm/dd') from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204356861.png" target="_blank"></a>
<b>其他格式:</b><b>year,month,mon,day,dy,am,ddsp,ddspth</b>
<b>格式内加入字元串請雙引。</b>
<b>SQL> select to_char(hiredate,'fmyyyy "</b><b>年</b><b>" mm "</b><b>月</b><b>" dd "</b><b>日</b><b>"') from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204405636.png" target="_blank"></a>
<b>目前距離零點的秒數</b><b>.</b>
<b>select sysdate,to_char(sysdate,'sssss') ss from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/204417317.png" target="_blank"></a>
<a href="http://blog.51cto.com/attachment/201205/204427713.png" target="_blank"></a>
<b>數字轉為字元串</b>
<b>格式為</b><b>9,0,$,l,.</b>
<b>col salary for a30</b>
<b>SQL> select ename,to_char(sal,'9999.000') salary from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204436598.png" target="_blank"></a>
<b>SQL> select ename,to_char(sal,'$00099999000.00' ) salary from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204449912.png" target="_blank"></a>
<b>SQL> select ename,to_char(sal,'l99,999.000') salary from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204504509.png" target="_blank"></a>
<b>SQL> select ename,TO_char(sal,'9G999D99') salary from emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204514706.png" target="_blank"></a>
9是代表有多少寬度,如果不足會顯示成######,0代表強制顯示0,但不會改變你的結果。G是千分符,D是小數點。
在資料庫中16進制的表達是按照字元串來描述的,是以你想将十進制的數轉換為十六進制的數使用to_char函數。
<b>SQL> select to_char(321,'xxxxx') from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/204600966.png" target="_blank"></a>
其中xxxxx的位數要足夠,不然報錯,你就多寫幾個,足夠大就可以。
<b> To_number,to_date</b>
如果你想将十六進制的數轉換為十進制的數請使用to_number函數。
<b>SQL> select to_number('abc32','xxxxxxxx') from dual;</b>
<a href="http://blog.51cto.com/attachment/201205/204608674.png" target="_blank"></a>
日期是格式和語言敏感的,切記!
SQL> select TO_NUMBER('100.00', '9G999D99') from dual;
<a href="http://blog.51cto.com/attachment/201205/204619769.png" target="_blank"></a>
G為千分符,D為小數點
<b>RR</b><b>和</b><b>yy</b><b>日期資料類型</b>
select to_char(sysdate,'yyyy') "目前",
to_char(to_date('98','yy'),'yyyy') "yy98",
to_char(to_date('08','yy'),'yyyy') "yy08",
to_char(to_date('98','rr'),'yyyy') "rr98",
to_char(to_date('08','rr'),'yyyy') "rr08" from dual;
結果為
<a href="http://blog.51cto.com/attachment/201205/204629410.png" target="_blank"></a>
yy是兩位來表示年,世紀永遠和說話者的目前世紀相同。
RR比較靈活,它将世紀分為上半世紀和下半世紀。如果你處于上半世紀,描述的是0-49,那麼就和目前世紀相同,描述的是50-99就是上世紀。如果你處于下半世紀,描述的是0-49,那麼是下個世紀,描述的是50-99就是目前世紀。進而可以看出,RR的設計完全為了1990年到2010之間我們的思維習慣而設計的。當我們時間到2050前後,使用起來就非常的别扭。
<b>實驗15:操作資料為null的函數</b>
該實驗的目的是掌握常用的關于NULL值操作的函數.
<b>綜合資料類型函數</b>
NVL (expr1, expr2)
如果expr1為非空,就傳回expr1, 如果expr1為空傳回expr2,兩個表達式的資料類型一定要相同。
NVL2 (expr1, expr2, expr3)
如果expr1為非空,就傳回expr2, 如果expr1為空傳回expr3
NULLIF (expr1, expr2)
如果expr1和 expr2相同就傳回空,否則傳回expr1
COALESCE (expr1, expr2, ..., exprn)
傳回括号内第一個非空的值。
<b>SQL> select ename,comm,nvl(comm,0) from emp;</b>
<b>有獎金就傳回獎金,獎金為空就傳回</b><b>0</b><b>。</b>
<a href="http://blog.51cto.com/attachment/201205/204757957.png" target="_blank"></a>
<b>select ename </b><b>姓名</b><b>,sal </b><b>工資</b><b>,comm </b><b>獎金</b><b>,sal+nvl(comm,0) </b><b>總工資</b><b>,nvl2(comm,'</b><b>工資加獎金</b><b>','</b><b>純工資</b><b>') "</b><b>收入類别</b><b>" from emp;</b>
<b>有獎金就傳回‘工資加獎金‘,獎金為空就傳回‘純工資’。</b>
<a href="http://blog.51cto.com/attachment/201205/204808976.png" target="_blank"></a>
<b>SQL> select ename,nullif(ename,'KING') from emp;</b>
<b>如果員工的名稱為</b><b>king</b><b>就傳回空,否則傳回自己的名字。</b>
<a href="http://blog.51cto.com/attachment/201205/204817171.png" target="_blank"></a>
<b>SQL> select ename </b><b>姓名</b><b>,COALESCE(comm,0) "</b><b>獎金</b><b>" from emp;</b>
<b>如果有獎金就傳回獎金,如果沒有獎金就傳回</b><b>0</b><b>,起個别名叫做</b><b>"</b><b>獎金</b><b>"</b><b>。</b>
<a href="http://blog.51cto.com/attachment/201205/204826646.png" target="_blank"></a>
<b>實驗16:分支的函數</b>
該實驗的目的是掌握分支操作的函數.
<b> </b><b>Case</b><b>語句</b>
9I以後才支援的新特性,說叫語句其實是函數。目的是為了分支。
CASE expr WHEN comparison_expr1 THEN return_expr1
[WHEN comparison_expr2 THEN return_expr2
WHEN comparison_exprn THEN return_exprn
ELSE else_expr]
END
<b>例子:</b>
例題:判别job,不同工作的人賦予不同的工資,除了CLERK,SALESMAN,ANALYST以外,其它的人工資不變,将函數的值起一個别名為"處理後資料"。
<b>語句:</b>
<b>SELECT ename, job, sal,</b>
<b>CASE job WHEN 'CLERK' THEN 1.1111*sal</b>
<b>WHEN 'SALESMAN' THEN 2.2222*sal</b>
<b>WHEN 'ANALYST' THEN 3.3333*sal</b>
<b>ELSE sal END "</b><b>處理後資料</b><b>"</b>
<b>FROM emp;</b>
<a href="http://blog.51cto.com/attachment/201205/204900915.png" target="_blank"></a>
<b>Decode</b><b>函數:</b>
和CASE語句一樣都是分支語句,但Decode函數是ORACLE自己定義的,其它資料庫可能不支援。
文法如下:
DECODE(col|expression, search1, result1
[, search2, result2,...,]
[, default])
<b>例題:判别</b><b>job,</b><b>不同工作的人賦予不同的工資,除了</b><b>CLERK</b><b>,</b><b>SALESMAN</b><b>,</b><b>ANALYST</b><b>以外,其它的人工資不變,将函數的值起一個别名為</b><b>"</b><b>處理後資料</b><b>"</b><b>。</b>
<b>decode(job ,'CLERK' , 1.11*sal</b>
<b>,'SALESMAN' , 3.33*sal</b>
<b>,'ANALYST' , 8.88*sal</b>
<b>, sal ) "</b><b>處理後資料</b><b>"</b>
<a href="http://blog.51cto.com/attachment/201205/204909412.png" target="_blank"></a>
<b>下面的例題是求稅率:</b>
<b>不同工資上的稅率不同。每</b><b>2000</b><b>一個台階,</b><b>8000</b><b>以上一律</b><b>40%</b><b>的稅。</b>
<b>SQL></b><b>SELECT ename, sal,</b>
<b>DECODE (TRUNC(sal/1000, 0),</b>
<b>0, 0.00,</b>
<b>1, 0.09,</b>
<b>2, 0.20,</b>
<b>3, 0.30</b>
<b>, 0.40</b>
<b>) </b><b>稅率</b>
<a href="http://blog.51cto.com/attachment/201205/204920104.png" target="_blank"></a>
<b>不管</b><b>CASE</b><b>語句還是</b><b>DECODE</b><b>函數,他們都是單行函數,每一行都有一個傳回值。從</b><b>ORACLE</b><b>角度來講,</b><b>DECODE</b><b>更好,因為各個版本的資料庫都支援,橫向來說,</b><b>CASE</b><b>語句更好,因為它是國标,不同的資料庫間都認可。</b>
<b>實驗17:分組統計函數</b>
該實驗的目的是掌握常用的組函數.了解group by的操作.
<b>需要掌握的知識點:</b>
1。組函數
2。分組統計
3。NULL值在組函數中的作用
4。HAVING的過濾作用
5。組函數的嵌套
<b> </b><b>組函數</b>
這種函數每次處理多行,給出一個傳回值
Avg平均
Sum求和
Max最大
Min最小
Count計數
<a href="http://blog.51cto.com/attachment/201205/205158923.png" target="_blank"></a>
所有組函數,除了count(*)以外,都忽略null值,count是計數,檢視有多少行,count(列)是檢視該列有多少非空的行。
<a href="http://blog.51cto.com/attachment/201205/205209163.png" target="_blank"></a>
<b>Group by </b><b>子句</b>
Having是在結果中再次篩選。Having一定得出現在group by 子句得後面。不能獨立存在。
<a href="http://blog.51cto.com/attachment/201205/205247975.png" target="_blank"></a>
組函數的嵌套注意要使用GROUP BY子句。
巧用DECODE函數,改變排版方式
<b>SQL></b>select 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",
sum(decode(to_char(hiredate,'yyyy'),'1987',1,0)) "1987",
count(ename) "總人數" from emp;
<a href="http://blog.51cto.com/attachment/201205/205258289.png" target="_blank"></a>
<b>《完》</b>
<b></b>
<b>本文轉自xjzhujunjie 51CTO部落格,原文連結:http://blog.51cto.com/xjzhujunjie/866373</b>