天天看點

Oracle 10g資料庫基礎之基本查詢語句-中-函數

 <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&gt; Select lower(ename),upper(ename),initcap(ename) from emp;

SQL&gt;Select lower(ename) 小寫字母,upper(ename) 大寫字母,initcap(ename) 首字母大寫 from emp;

<a href="http://blog.51cto.com/attachment/201205/203032223.png" target="_blank"></a>

SQL&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; select ceil(45.001) from dual;</b>

<a href="http://blog.51cto.com/attachment/201205/203738312.png" target="_blank"></a>

<b>取絕對值</b>

<b>SQL&gt; select abs(-23.00) from dual;</b>

<a href="http://blog.51cto.com/attachment/201205/203749330.png" target="_blank"></a>

<b>取餘數</b>

<b>SQL&gt; 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&gt; select sysdate from dual;

日期的顯示格式和用戶端的配置相關。

<a href="http://blog.51cto.com/attachment/201205/203955836.png" target="_blank"></a>

<b>檢視目前的日期顯示格式</b>

SQL&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; 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&gt; select to_number('abc32','xxxxxxxx') from dual;</b>

<a href="http://blog.51cto.com/attachment/201205/204608674.png" target="_blank"></a>

日期是格式和語言敏感的,切記!

SQL&gt; 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&gt; 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&gt; 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&gt; 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&gt;</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&gt;</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>