[
推薦
]
ORACLE?PL/SQL
編程詳解之
三
:
PL/SQL
流程控制語句
(
不給規則
,
不成方圓
)
——
通過知識共享樹立個人品牌。
繼上
五
篇:
???
[
頂
]ORACLE?PL/SQL
編程詳解之二:
PL/SQL
塊結構和組成元素
(
為山九仞,豈一日之功
)
??? [ 推薦 ]ORACLE?PL/SQL 編程之四:把游標說透 ( 不怕做不到,只怕想不到 )
?
???? [ 推薦 ]ORACLE?PL/SQL 編程之五:異常錯誤處理 ( 知已知彼、百戰不殆 )
?? ? ORACLE?PL/SQL 編程之六:把過程與函數說透 ( 窮追猛打,把根兒都拔起 !)? ?
?
?????
ORACLE?PL/SQL
編程之八:把觸發器說透
?
接下來 再次 介紹PL/SQL的基礎篇:PL/SQL流程控制語句,還望大家繼續支持與推薦~!
?
本篇主要內容如下:
?
介紹
PL/SQL
的流程控制語句
,?
包括如下三類
:
l?
控制語句
:?IF?
語句
l?
循環語句
:?LOOP
語句
,?EXIT
語句
l? 順序語句 :?GOTO 語句 ,?NULL 語句
3.1??
條件語句
?
??PL / SQL?和?SQL語句
END ? IF ;
-- ---------------------
IF ? < 布爾表達式 > ? THEN
??PL / SQL?和?SQL語句
ELSE
??其它語句
END ? IF ;
-- ---------------------
IF ? < 布爾表達式 > ? THEN
??PL / SQL?和?SQL語句
ELSIF? < ?其它布爾表達式 > ? THEN
??其它語句
ELSIF? < ?其它布爾表達式 > ? THEN
??其它語句
ELSE
??其它語句
END ? IF ;
?
?
提示
:?ELSIF?
不能寫成?
ELSEIF
例
1:
?
????v_empno??employees.employee_id % TYPE?: =& empno;
????V_salary?employees.salary % TYPE;
????V_comment? VARCHAR2 ( 35 );
BEGIN
??? SELECT ?salary? INTO ?v_salary? FROM ?employees?
??? WHERE ?employee_id? = ?v_empno;
??? IF ?v_salary? < ? 1500 ? THEN
???????V_comment: = ? ' 太少了,加點吧~! ' ;
???ELSIF?v_salary? < 3000 ? THEN
??????V_comment: = ? ' 多了點,少點吧~! ' ;
??? ELSE
??????V_comment: = ? ' 沒有薪水~! ' ;
??? END ? IF ;
???DBMS_OUTPUT.PUT_LINE(V_comment);
???exception
????? when ?no_data_found? then
????????DBMS_OUTPUT.PUT_LINE( ' 沒有數據~! ' );
????? when ?others? then
????????DBMS_OUTPUT.PUT_LINE(sqlcode? || ? ' --- ' ? || ?sqlerrm);????????
END ;
?
?
例
2
:
?
???v_first_name?? VARCHAR2 ( 20 );
???v_salary? NUMBER ( 7 , 2 );
BEGIN
??? SELECT ?first_name,?salary? INTO ?v_first_name,?v_salary? FROM ?employees
??? WHERE ?employee_id? = ? & emp_id;
???DBMS_OUTPUT.PUT_LINE(v_first_name || ' 雇員的工資是 ' || v_salary);
??? IF ?v_salary? < ? 10000 ? THEN
??????DBMS_OUTPUT.PUT_LINE( ' 工資低于10000 ' );
??? ELSE
?????? IF ? 10000 ? <= ?v_salary? AND ?v_salary? < ? 20000 ? THEN
?????????DBMS_OUTPUT.PUT_LINE( ' 工資在10000到20000之間 ' );
?????? ELSE
?????????DBMS_OUTPUT.PUT_LINE( ' 工資高于20000 ' );
?????? END ? IF ;
??? END ? IF ;
END ;
?
?
例
3
:
DECLARE
???v_first_name??
VARCHAR2
(
20
);
???v_hire_date?DATE;
???v_bonus?
NUMBER
(
6
,
2
);
BEGIN
???
SELECT
?first_name,?hire_date?
INTO
?v_first_name,?v_hire_date?
FROM
?employees
???
WHERE
?employee_id?
=
?
&
emp_id;
???
IF
?v_hire_date?
>
?TO_DATE(
'
01-1月-90
'
)?
THEN
??????v_bonus?:
=
?
800
;
???ELSIF?v_hire_date?
>
?TO_DATE(
'
01-1月-88
'
)?
THEN
??????v_bonus?:
=
?
1600
;
???
ELSE
??????v_bonus?:
=
?
2400
;
???
END
?
IF
;
???DBMS_OUTPUT.PUT_LINE(v_first_name
||
'
雇員的雇傭日期是
'
||
v_hire_date
????????????????????????????????????
||
'
、獎金是
'
||
v_bonus);
END
;
???v_first_name?? VARCHAR2 ( 20 );
???v_hire_date?DATE;
???v_bonus? NUMBER ( 6 , 2 );
BEGIN
??? SELECT ?first_name,?hire_date? INTO ?v_first_name,?v_hire_date? FROM ?employees
??? WHERE ?employee_id? = ? & emp_id;
??? IF ?v_hire_date? > ?TO_DATE( ' 01-1月-90 ' )? THEN
??????v_bonus?: = ? 800 ;
???ELSIF?v_hire_date? > ?TO_DATE( ' 01-1月-88 ' )? THEN
??????v_bonus?: = ? 1600 ;
??? ELSE
??????v_bonus?: = ? 2400 ;
??? END ? IF ;
???DBMS_OUTPUT.PUT_LINE(v_first_name || ' 雇員的雇傭日期是 ' || v_hire_date
???????????????????????????????????? || ' 、獎金是 ' || v_bonus);
END ;
?
3.2??CASE?
表達式
?
CASE ?條件表達式
?? WHEN ?條件表達式結果1? THEN ?
?????語句段1
?? WHEN ?條件表達式結果2? THEN
?????語句段2
??......
?? WHEN ?條件表達式結果n? THEN
?????語句段n
?? [ ELSE?條件表達式結果 ]
END ;
-- -------格式二---------
CASE ?
?? WHEN ?條件表達式1? THEN
?????語句段1
?? WHEN ?條件表達式2? THEN
?????語句段2
??......
?? WHEN ?條件表達式n? THEN ?
?????語句段n
?? [ ELSE?語句段 ]
END ;
?
?
例
4
:
?
??V_grade? char ( 1 )?: = ? UPPER ( ' &p_grade ' );
??V_appraisal? VARCHAR2 ( 20 );
BEGIN
??V_appraisal?: =
?? CASE ?v_grade
???? WHEN ? ' A ' ? THEN ? ' Excellent '
???? WHEN ? ' B ' ? THEN ? ' Very?Good '
???? WHEN ? ' C ' ? THEN ? ' Good '
???? ELSE ? ' No?such?grade '
?? END ;
??DBMS_OUTPUT.PUT_LINE( ' Grade: ' || v_grade || ' ??Appraisal:? ' || ?v_appraisal);
END ;
?
?
例
5:
?
???v_first_name?employees.first_name % TYPE;
???v_job_id?employees.job_id % TYPE;
???v_salary?employees.salary % TYPE;
???v_sal_raise? NUMBER ( 3 , 2 );
BEGIN
??? SELECT ?first_name,???job_id,???salary? INTO
??????????v_first_name,?v_job_id,?v_salary
??? FROM ?employees? WHERE ?employee_id? = ? & emp_id;
??? CASE
?????? WHEN ?v_job_id? = ? ' PU_CLERK ' ? THEN
????????? IF ?v_salary? < ? 3000 ? THEN ?v_sal_raise?: = ?. 08 ;
????????? ELSE ?v_sal_raise?: = ?. 07 ;
????????? END ? IF ;
?????? WHEN ?v_job_id? = ? ' SH_CLERK ' ? THEN
????????? IF ?v_salary? < ? 4000 ? THEN ?v_sal_raise?: = ?. 06 ;
????????? ELSE ?v_sal_raise?: = ?. 05 ;
????????? END ? IF ;
?????? WHEN ?v_job_id? = ? ' ST_CLERK ' ? THEN
????????? IF ?v_salary? < ? 3500 ? THEN ?v_sal_raise?: = ?. 04 ;
????????? ELSE ?v_sal_raise?: = ?. 03 ;
????????? END ? IF ;
?????? ELSE
?????????DBMS_OUTPUT.PUT_LINE( ' 該崗位不漲工資:? ' || v_job_id);
??? END ? CASE ;
???DBMS_OUTPUT.PUT_LINE(v_first_name || ' 的崗位是 ' || v_job_id
???????????????????????????????????? || ' 、的工資是 ' || v_salary
???????????????????????????????????? || ' 、工資漲幅是 ' || v_sal_raise);
END ;
?
?
?
3.3??
循環
?1.??
簡單循環
?
??????要執行的語句;
?????? EXIT ? WHEN ? < 條件語句 > ? -- 條件滿足,退出循環語句
?? END ?LOOP;
?
?
例?
6
.
?
???? int ? NUMBER ( 2 )?: = 0 ;
BEGIN
???LOOP
?????? int ?: = ? int ? + ? 1 ;
??????DBMS_OUTPUT.PUT_LINE( ' int?的當前值為: ' || int );
?????? EXIT ? WHEN ? int ? = 10 ;
??? END ?LOOP;
END ;
?
?
2.??WHILE? 循環
????要執行的語句;
END ?LOOP;
?
例
7
.
?
??x? NUMBER ?: = 1 ;
BEGIN
??? WHILE ?x <= 10 ?LOOP
??????DBMS_OUTPUT.PUT_LINE( ' X的當前值為: ' || x);
???????x: = ?x + 1 ;
??? END ?LOOP;
END ;
?
?
3.??
數字式循環
?
FOR ?循環計數器? IN ? [ ?REVERSE? ] ?下限?..?上限?LOOP
??要執行的語句;
END ?LOOP? [ 循環標簽 ] ;
?
?
每循環一次,循環變量自動加
1
;使用關鍵字
REVERSE
,循環變量自動減
1
。跟在
IN?REVERSE?
后面的數字必須是從小到大的順序,而且必須是整數,不能是變量或表達式。可以使用
EXIT?
退出循環。
例
8
.
?
??? FOR ? int ?? in ? 1 .. 10 ?LOOP
???????DBMS_OUTPUT.PUT_LINE( ' int?的當前值為:? ' || int );
??? END ?LOOP;
END ;
?
?
例?
9
.
?
DECLARE
????V_counter? NUMBER ?: = ? 10 ;
BEGIN
??? INSERT ? INTO ?temp_table(num_col)? VALUES ?(v_counter?);
??? FOR ?v_counter? IN ? 20 ?..? 25 ?LOOP
?????? INSERT ? INTO ?temp_table?(num_col?)? VALUES ?(?v_counter?);
??? END ?LOOP;
??? INSERT ? INTO ?temp_table(num_col)? VALUES ?(v_counter?);
??? FOR ?v_counter? IN ? REVERSE ? 20 ?..? 25 ?LOOP
?????? INSERT ? INTO ?temp_table?(num_col?)? VALUES ?(?v_counter?);
??? END ?LOOP;
END ?;
DROP ? TABLE ?temp_table;
?
?
例
10:
?
???TYPE?jobids_varray? IS ?VARRAY( 12 )? OF ? VARCHAR2 ( 10 );? -- 定義一個VARRAY數據類型
???v_jobids?JOBIDS_VARRAY;? -- 聲明一個具有JOBIDS_VARRAY數據類型的變量
???v_howmany? NUMBER ;? -- 聲明一個變量來保存雇員的數量
BEGIN
??? -- 用某些job_id值初始化數組
???v_jobids?: = ?jobids_varray( ' FI_ACCOUNT ' ,? ' FI_MGR ' ,? ' ST_CLERK ' ,? ' ST_MAN ' );
??? -- 用FOR...LOOP...END?LOOP循環使用每個數組成員的值
??? FOR ?i? IN ?v_jobids.FIRST..v_jobids.LAST?LOOP
??? -- 針對數組中的每個崗位,決定該崗位的雇員的數量
?????? SELECT ? count ( * )? INTO ?v_howmany? FROM ?employees? WHERE ?job_id? = ?v_jobids(i);
??????DBMS_OUTPUT.PUT_LINE?(? ' 崗位 ' || v_jobids(i) ||
??????????????????????? ' 總共有 ' || ?TO_CHAR(v_howmany)? || ? ' 個雇員 ' );
??? END ?LOOP;
END ;
?
?
例
11?
在
While
循環中嵌套
loop
循環
/*
求100至110之間的素數
*/
DECLARE
???v_m?
NUMBER
?:
=
?
101
;
???v_i?
NUMBER
;
???v_n?
NUMBER
?:
=
?
0
;
BEGIN
???
WHILE
?v_m?
<
?
110
?LOOP
??????v_i?:
=
?
2
;
??????LOOP
?????????
IF
?mod(v_m,?v_i)?
=
?
0
?
THEN
????????????v_i?:
=
?
0
;
????????????
EXIT
;
?????????
END
?
IF
;
????
?????????v_i?:
=
?v_i?
+
?
1
;
?????????
EXIT
?
WHEN
?v_i?
>
?v_m?
-
?
1
;?
??????
END
?LOOP;
??????
??????
IF
?v_i?
>
?
0
?
THEN
?????????v_n?:
=
?v_n?
+
?
1
;
?????????DBMS_OUTPUT.PUT_LINE(
'
第
'
||
?v_n?
||
?
'
個素數是
'
?
||
?v_m);
??????
END
?
IF
;
??????v_m?:
=
?v_m?
+
?
2
;
???
END
?LOOP;
END
;
DECLARE
???v_m? NUMBER ?: = ? 101 ;
???v_i? NUMBER ;
???v_n? NUMBER ?: = ? 0 ;
BEGIN
??? WHILE ?v_m? < ? 110 ?LOOP
??????v_i?: = ? 2 ;
??????LOOP
????????? IF ?mod(v_m,?v_i)? = ? 0 ? THEN
????????????v_i?: = ? 0 ;
???????????? EXIT ;
????????? END ? IF ;
????
?????????v_i?: = ?v_i? + ? 1 ;
????????? EXIT ? WHEN ?v_i? > ?v_m? - ? 1 ;?
?????? END ?LOOP;
??????
?????? IF ?v_i? > ? 0 ? THEN
?????????v_n?: = ?v_n? + ? 1 ;
?????????DBMS_OUTPUT.PUT_LINE( ' 第 ' || ?v_n? || ? ' 個素數是 ' ? || ?v_m);
?????? END ? IF ;
??????v_m?: = ?v_m? + ? 2 ;
??? END ?LOOP;
END ;
?
3.
4
??標號和
GOTO
?
PL/SQL
中
GOTO
語句是無條件跳轉到指定的標號去的意思。語法如下:
?
......
<< label >> /* 標號是用<< >>括起來的標識符? */
?
?
注意
,在以下地方使用是不合法的,編譯時會出錯誤。
u?
跳轉到非執行語句前面。
u?
跳轉到子塊中。
u?
跳轉到循環語句中。
u?
跳轉到條件語句中。
u?
從異常處理部分跳轉到執行。
u?
從條件語句的一部分跳轉到另一部分。
例
12
:
?
???V_counter? NUMBER ?: = ? 1 ;
BEGIN
???LOOP?
?????DBMS_OUTPUT.PUT_LINE( ' V_counter的當前值為: ' || V_counter);
?????V_counter?: = ?v_counter? + ? 1 ;
??? IF ?v_counter? > ? 10 ? THEN
??????? GOTO ?labelOffLOOP;
??? END ? IF ;
??? END ?LOOP;
??? << labelOffLOOP >>
?????DBMS_OUTPUT.PUT_LINE( ' V_counter的當前值為: ' || V_counter);
END ;
?
?
例
13:
DECLARE
???v_i?
NUMBER
?:
=
?
0
;
???v_s?
NUMBER
?:
=
?
0
;
BEGIN
???
<<
label_1
>>
???v_i?:
=
?v_i?
+
?
1
;
???
IF
?v_i?
<=
?
1000
?
THEN
??????v_s?:
=
?v_s?
+
?v_i;
??????
GOTO
?label_1;
???
END
?
IF
;
???DBMS_OUTPUT.PUT_LINE(v_s);
END
;
???v_i? NUMBER ?: = ? 0 ;
???v_s? NUMBER ?: = ? 0 ;
BEGIN
??? << label_1 >>
???v_i?: = ?v_i? + ? 1 ;
??? IF ?v_i? <= ? 1000 ? THEN
??????v_s?: = ?v_s? + ?v_i;
?????? GOTO ?label_1;
??? END ? IF ;
???DBMS_OUTPUT.PUT_LINE(v_s);
END ;
?
3.
5
??NULL?
語句
?
在
PL/SQL?
程序中,
NULL
語句是一個可執行語句,
可以用?
null?
語句來說明
“
不用做任何事情
”
的意思,相當于一個占位符
或不執行任何操作的空語句
,可以使某些語句變得有意義,提高程序的可讀性
,保證其他語句結構的完整性和正確性
。如:
例
14:
?
????...
BEGIN
????...
???? IF ?v_num? IS ? NULL ? THEN
???? GOTO ?labelPrint;
???? END ? IF ;
??…
?? << labelPrint >>
?? NULL ;? -- 不需要處理任何數據。
END ;
?
例 15:
?
???v_emp_id?employees.employee_id % TYPE;
???v_first_name?employees.first_name % TYPE;
???v_salary?employees.salary % TYPE;
???v_sal_raise? NUMBER ( 3 , 2 );
BEGIN
???v_emp_id?: = ? & emp_id;
??? SELECT ?first_name,?salary? INTO ?v_first_name,?v_salary
??? FROM ?employees? WHERE ?employee_id? = ?v_emp_id;
??? IF ?v_salary? <= ? 3000 ? THEN
??????v_sal_raise?: = ?. 10 ;
??????DBMS_OUTPUT.PUT_LINE(v_first_name || ' 的工資是 ' || v_salary
??????????????????????????????????????? || ' 、工資漲幅是 ' || v_sal_raise);
??? ELSE
?????? NULL ;
??? END ? IF ;
END ;
?
??2011??
EricHu
原創作品,轉貼請注明作者和出處,留此信息。
------------------------------------------------
cnBlobs:
http://www.cnblogs.com/huyong/
CSDN
:
http://blog.csdn.net/chinahuyong
?
作者:
EricHu
(
DB
、
C\S
、
B\S
、
WebService
、
WCF
、
PM
等
)
出處:
http://
www
.cnblogs.com
/huyong/
Q?Q
:
80368704???E-Mail:?80368704@qq.com
本博文歡迎大家瀏覽和轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,在『參考』的文章中,我會表明參考的文章來源,尊重他人版權。若您發現我侵犯了您的版權,請及時與我聯系。
更多文章請看
?
[
置頂
]
索引貼
——
(不斷更新中)
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
