(B):其中語(yǔ)句CURSOR desc_salary(emp_id NUMBER) RETURN EMPRECTYP定義了一個(gè)游標(biāo)desc_salary。
游標(biāo)(CURSOR)詳見本節(jié)最后的內(nèi)容。
?。w建立
CREATE PACKAGE BODY emp_actions AS
CURSOR desc_salary(emp_id NUMBER)RETURN EMPRECTYP
IS SELECT EMPNO,SAL FROM emp ORDER BY SAL DESC;
PROCEDURE hire_employee
(ename CHAR,
job CHAR,
sal NUMBER,
mgr NUMBER,
comm NUMBER,
deptno NUMBER)IS
BEGIN
INSERT INTO EMP VALUES(EMPNO_SEQ.NEXTVAL,
ename,job,mgr,SYSDATE,sal,comm,deptno);
END hire_employee;
PROCEDURE fire_employee(emp_id NUMBER) IS
BEGIN
DELETE FROM EMP WHERE EMPNO=emp_id;
END fire_employee;
END emp_actions;
注重:hire_employee過(guò)程使用參數(shù),數(shù)據(jù)庫(kù)序列empno_seq、函數(shù)SYSDATE插入一個(gè)新職工記錄,其職工號(hào)由序列產(chǎn)生,聘用日期由函數(shù)
SYSDATE生成。
在包說(shuō)明中,說(shuō)明對(duì)所有應(yīng)用是可見的而且可存取。在包體中,實(shí)現(xiàn)細(xì)節(jié)是隱藏的,不可存取。所以改變包體不會(huì)引起調(diào)用程序的重新編譯。
在設(shè)計(jì)一個(gè)應(yīng)用時(shí),最初只需要定義包說(shuō)明的接口信息。在沒(méi)有包體時(shí)可編制包說(shuō)明的程序并進(jìn)行編譯。一旦包說(shuō)明已經(jīng)被編譯,引用該包的存貯子程序同樣編譯。在完成應(yīng)用之前,可不必定義包體。調(diào)試、提高或替換一個(gè)包體不必修改包說(shuō)明,以致不需重新編譯調(diào)用程序。在包說(shuō)明中所說(shuō)明的游標(biāo)和子程序必須在包體中定義。
(3)對(duì)包裝子程序的調(diào)用
包裝的子程序可被數(shù)據(jù)庫(kù)觸發(fā)器、其它的存貯子程序、Oracle預(yù)編譯應(yīng)用程序、OCI應(yīng)用程序或ORACLE工具(如SQL*PLUS)調(diào)用,其調(diào)用形式如下:
?。畯牧硪淮尜A子程序調(diào)用
存貯子程序可調(diào)用包裝子程序。
例2.53: 調(diào)用包EMP_ACTIONS中的包裝過(guò)程HIRE_EMPLOYEE,其形式為:
EMP_ACTIONS.HIRE_EMPLOYEE(name,title,...);
?。畯膽?yīng)用程序中調(diào)用
一個(gè)ORACLE預(yù)編譯的應(yīng)用程序或OCI應(yīng)用程序可用無(wú)名PL/SQL塊調(diào)用包裝子程序。
例2.54: 在ORACLE預(yù)編譯應(yīng)用程序?qū)Πb過(guò)程HIRE_EMPLOYEE調(diào)用,形式為:
EXEC SQL EXECUTE
BEGIN
EMP_ACTIONS.HIRE_EMPLOYEE(:name,:title,...);
END;
END_EXEC;
其中實(shí)在參數(shù)name、title為宿主變量。
?。畯腛RACLE工具中調(diào)用
可從ORACLE工具(如SQL*PLUS、SQL*FORMS和SQL*DBA)中交互地調(diào)用包裝子程序。其調(diào)用形式為:
SQL>EXECUTE EMP_ACTIONS.HIRE_EMPLOYEE(‘TATE’,’CLERK’,...);
注重:在執(zhí)行一個(gè)包裝子程序之前,ORACLE標(biāo)志一個(gè)隱式的保留點(diǎn)。假如子程序由于具有未處理例外而失敗時(shí),在返回到宿主環(huán)境之前,ORACLE將回滾到該保留點(diǎn)上.
在一個(gè)包裝子程序中可包含任何SQL語(yǔ)句和PL/SQL語(yǔ)句。然而,凡參與分布工事務(wù)、數(shù)據(jù)庫(kù)觸發(fā)器、SQL*FORM應(yīng)用程序的子程序不能調(diào)用包含有COMMIT、ROLLBACK、SAVEPOINT語(yǔ)句的包裝子程序。
.遠(yuǎn)程存取
可利用下列語(yǔ)法調(diào)用存貯在遠(yuǎn)程ORACLE數(shù)據(jù)庫(kù)中的包裝子程序:
包名.子程序名@DB鏈名(參數(shù)1,參數(shù)2,...)
ORACLE在數(shù)據(jù)字典中分別存貯包說(shuō)明和包體。其它對(duì)象僅可引用包說(shuō)明中全局包對(duì)象,重新定義包體中的對(duì)象時(shí)不會(huì)引起ORACLE使從屬對(duì)象無(wú)效。
(4) STANDARD包和產(chǎn)品特有的包
名為STANDARD的包定義了PL/SQL環(huán)境。該包說(shuō)明全局的申明類型、例外和子程序,可自動(dòng)地適用于每一個(gè)PL/SQL程序。STANDARD包的內(nèi)容對(duì)應(yīng)用是直接可見的。許多內(nèi)部函數(shù)是被重載的。
為了方便建立基于PL/SQL的應(yīng)用程序,ORACLE SERVER和幾種ORACLE工具都有產(chǎn)品特有的包,例SQL*FORMS提供名為SQLFORMS的包。如需要更多信息,請(qǐng)參見相應(yīng)產(chǎn)品的引用手冊(cè)。
三、控制結(jié)構(gòu)
本節(jié)介紹PL/SQL程序的控制流結(jié)構(gòu)。
根據(jù)結(jié)構(gòu)化程序設(shè)計(jì)理論,任何程序可同三種基本控制結(jié)構(gòu)組成:分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu)和順序結(jié)構(gòu)。PL/SQL也用相應(yīng)的語(yǔ)句來(lái)支持這三種控制結(jié)構(gòu)。
1.條件控制IF語(yǔ)句
IF語(yǔ)句是條件執(zhí)行語(yǔ)句。IF語(yǔ)句有三種形式:IF_THEN,IF_THEN_ELSE和IF_THEN_ELSIF。
(1) IF_THEN形式
它是IF語(yǔ)句最簡(jiǎn)單形式,將一條件與一語(yǔ)句序列相聯(lián)。當(dāng)條件為TRUE時(shí),執(zhí)行語(yǔ)句序列。
例 2.55:
IF X>Y THEN high:=X;ENDIF
(2) IF_THEN_ELSE形式
該種IF語(yǔ)句形式比簡(jiǎn)單形式增加要害字ELSE,后跟另一語(yǔ)句序列。形式為:
IF 條件 THEN
語(yǔ)句序列1;
ELSE
語(yǔ)句序列2;
ENDIF;
ELSE子句中語(yǔ)句序列僅當(dāng)條件計(jì)算為FALSE或NULL時(shí)執(zhí)行。在THEN和ELSE子句中可包含IF語(yǔ)句,即IF語(yǔ)句可以嵌套。
(3) IF_THEN_ELSIF形式
該形式利用ELSIF要害字引入附加條件。形式為:
IF 條件1 THEN
語(yǔ)句序列1;
ELSIF 條件2 THEN
語(yǔ)句序列2;
ELSE
語(yǔ)句序列3;
ENDIF;
當(dāng)條件1計(jì)算得FALSE或NULL時(shí),ELSIF子句測(cè)試條件2,為TRUE時(shí),則執(zhí)行語(yǔ)句序列2。IF語(yǔ)句可以有任何數(shù)目的ELSIF語(yǔ)句,而最后的ELSE子句是可選項(xiàng)。在此種情況下,每一條件對(duì)應(yīng)一語(yǔ)句序列,條件由頂向底計(jì)算。任何一個(gè)條件計(jì)算為TRUE時(shí),執(zhí)行相對(duì)應(yīng)的語(yǔ)句序列。假如所有條件計(jì)算為FALSE或NULL,則執(zhí)行ELSE子句中的序列。
例 2.56:
IF X>Y THEN
high:=X;
ELSIF X=Y THEN
B:=FALSE;
ELSE
C:=NULL;
ENDIF;
其中,B和C是布爾數(shù)據(jù)類型(BOOLEAN)。布爾數(shù)據(jù)類型用于存貯TRUE、FALSE或NULL(空值)。它沒(méi)有參數(shù),僅可將三種值賦給一個(gè)布爾變量,不能將TRUE、FALSE值插入到數(shù)據(jù)庫(kù)的列,也不能從數(shù)據(jù)庫(kù)的列中選擇或獲取列值到BOOLEAN變量。
2.循環(huán)語(yǔ)句:LOOP和EXIT語(yǔ)句
(1) 基本循環(huán)
基本循環(huán)(或無(wú)限循環(huán))是循環(huán)語(yǔ)句的最簡(jiǎn)單的形式,它由要害字LOOP和ENDLOOP之間的語(yǔ)句序列組成。每一次循環(huán)迭代,語(yǔ)句序列執(zhí)行一次,然后控制重新由循環(huán)的頂部開始??衫肊XIT、GOTO或RAISE語(yǔ)句退出循環(huán)?;狙h(huán)形式為:
LOOP
語(yǔ)句序列;
EXIT WHEN 布爾表達(dá)式;
ENDLOOP;
其中EXIT語(yǔ)句用于退出循環(huán)。EXIT語(yǔ)句有兩種形式:無(wú)條件的EXIT和條件的EXIT[標(biāo)號(hào)名]WHEN。[標(biāo)號(hào)名]選項(xiàng)中的標(biāo)號(hào)名為所要退出的循環(huán)標(biāo)識(shí)。使用標(biāo)號(hào)名不僅可退出當(dāng)前循環(huán),而且可退出由標(biāo)號(hào)名所標(biāo)識(shí)的循環(huán)。
不能用EXIT語(yǔ)句退出一個(gè)PL/SQL塊。
(2) WHILE_LOOP循環(huán)
WHILE_LOOP循環(huán)語(yǔ)句將一條件與一由要害字LOOP和ENDLOOP包裝的語(yǔ)句序列相聯(lián)系。在每次循環(huán)開始前,計(jì)算條件,假如該條件計(jì)算得到TRUE,執(zhí)行語(yǔ)句序列,然后控制重新回到循環(huán)頂部。假如條件計(jì)算得到FALSE或NULL,結(jié)束循環(huán)。在循環(huán)中引起例外時(shí)也結(jié)束循環(huán)。該語(yǔ)句的形式為:
WHILE 條件 LOOP
語(yǔ)句序列,
END LOOP;
例 2.57:
WHILE total<=25000 LOOP
...
SELECT INTO Salary From emp WHERE...;
total:=total+Salary;
ENDLOOP;
循環(huán)迭代次數(shù)依靠于條件,在循環(huán)完成之前是未知的。由于條件的測(cè)試是在循環(huán)的頂部,語(yǔ)句序列可以一次也不執(zhí)行。
(3) 數(shù)值FOR_LOOP循環(huán)
數(shù)值FOR循環(huán)語(yǔ)句在一指定整數(shù)范圍中循環(huán),所以通過(guò)該循環(huán)的迭代次數(shù)是已知的。在第一次進(jìn)入FOR循環(huán)時(shí)計(jì)算范圍,之后再不重新計(jì)算。對(duì)由整數(shù)表達(dá)式1..整數(shù)表達(dá)式2定義的范圍中每一整數(shù),語(yǔ)句序列執(zhí)行一次,每次迭代之后,循環(huán)索引增加。
索引名為命名循環(huán)索引的標(biāo)識(shí)符,索引名無(wú)需說(shuō)明,它被隱式地說(shuō)明為INTEGER類型的變量。該索引名的范圍是該循環(huán)本身,在循環(huán)外不能存取。注重隱式說(shuō)明壓倒任何循環(huán)外的任何其它說(shuō)明。
整數(shù)表達(dá)式1、整數(shù)表達(dá)式2是表達(dá)式,計(jì)算出一個(gè)整數(shù)。要求整數(shù)表達(dá)式1的值不大于整數(shù)表達(dá)式2的值。
REVERSE選擇:缺省時(shí),迭代由低界向高界處理。但使用REVERSE后,迭代是由高界向低界處理,每次迭代后,循環(huán)索引減小。
數(shù)值FOR循環(huán)語(yǔ)句形式為:
FOR計(jì)數(shù)器IN[REVERSE]低界..高界LOOP
語(yǔ)句序列;
ENDLOOP;
例 2.58:
FOR I IN 1..3 LOOP --將值1,2,3賦給I
語(yǔ)句序列; --執(zhí)行三次
ENDLOOP;
3. 順序控制
GOTO語(yǔ)句和NULL語(yǔ)句對(duì)PL/SQL程序設(shè)計(jì)不像IF語(yǔ)句和循環(huán)語(yǔ)句那么重要,但有時(shí)PL/SQL結(jié)構(gòu)還是需要。
(1) GOTO語(yǔ)句
GOTO語(yǔ)句無(wú)條件轉(zhuǎn)移到一標(biāo)號(hào),該標(biāo)號(hào)應(yīng)在它的范圍內(nèi)是唯一的,它必須位于可執(zhí)行語(yǔ)