PL-SQL 包的創建和應用
①簡介
包是一組相關過程、函數、變量、常量和遊標等PL/SQL程序設計元素的組合,它具有面向對象程序設計語言的特點,是對這些PL/SQL 程序設計元素的封裝。
包類似於C++和JAVA語言中的類,其中變量相當於類中的成員變量,過程和函數相當於類方法。
把相關的模塊歸類成爲包,可使開發人員利用面向對象的方法進行存儲過程的開發,從而提高系統性能。
與類相同,包中的程序元素也分爲公用元素和私用元素兩種,這兩種元素的區別是他們允許訪問的程序範圍不同,即它們的作用域不同。
公用元素不僅可以被包中的函數、過程所調用,也可以被包外的PL/SQL程序訪問,而私有元素只能被包內的函數和過程序所訪問。
在PL/SQL程序設計中,使用包不僅可以使程序設計模塊化,對外隱藏包內所使用的信息(通過使用私用變量),而且可以提高程序的執行效率。
因爲,當程序首次調用包內函數或過程時,ORACLE將整個包調入內存,當再次訪問包內元素時,ORACLE直接從內存中讀取,而不需要進行磁盤I/O操作,
從而使程序執行效率得到提高。
一個包由兩個分開的部分組成:
包定義(PACKAGE):包定義部分聲明包內數據類型、變量、常量、遊標、子程序和異常錯誤處理等元素,這些元素爲包的公有元素。
包主體(PACKAGE BODY):包主體則是包定義部分的具體實現,它定義了包定義部分所聲明的遊標和子程序,在包主體中還可以聲明包的私有元素。
包定義和包主體分開編譯,並作爲兩部分分開的對象存放在數據庫字典中,詳見數據字典user_source, all_source, dba_source.
②包的定義
包定義的語法如下:
1.創建包定義:
CREATE[OR REPLACE] PACKAGE package_name
[AUTHID {CURRENT_USER | DEFINER}]
{IS| AS}
[公有數據類型定義[公有數據類型定義]…]
[公有遊標聲明[公有遊標聲明]…]
[公有變量、常量聲明[公有變量、常量聲明]…]
[公有子程序聲明[公有子程序聲明]…]
END[package_name];
其中:AUTHID CURRENT_USER和AUTHID DEFINER選項說明應用程序在調用函數時所使用的權限模式,
它們與CREATE FUNCTION語句中invoker_right_clause子句的作用相同。
創建包主體:
CREATE[OR REPLACE] PACKAGE BODYpackage_name
{IS| AS}
[私有數據類型定義[私有數據類型定義]…]
[私有變量、常量聲明[私有變量、常量聲明]…]
[私有子程序聲明和定義[私有子程序聲明和定義]…]
[公有遊標定義[公有遊標定義]…]
[公有子程序定義[公有子程序定義]…]
BEGIN
PL/SQL 語句
END[package_name];
其中:在包主體定義公有程序時,它們必須與包定義中所聲明子程序的格式完全一致。
對包內共有元素的調用格式爲:包名.元素名稱
③子程序重載
PL/SQL 允許對包內子程序和本地子程序進行重載。
所謂重載時指兩個或多個子程序有相同的名稱,但擁有不同的參數變量、參數順序或參數數據類型。
④刪除包
可以使用DROP PACKAGE命令對不需要的包進行刪除,語法如下:
DROP PACKAGE [BODY] [user.]package_name;
⑤包的管理
DBA_SOURCE, USER_SOURCE, USER_ERRORS, DBA-OBJECTS
⑥例子:
創建的包爲demo_pack, 該包中包含一個記錄變量DeptRec、兩個函數和一個過程。
CREATE OR REPLACE PACKAGE demo_pack
IS
DeptRec dept%ROWTYPE;
FUNCTION add_dept(dept_no NUMBER, dept_name VARCHAR2, location VARCHAR2)
RETURN NUMBER;
FUNCTION remove_dept(dept_no NUMBER)
RETURN NUMBER;
PROCEDURE query_dept(dept_no IN NUMBER);
END demo_pack
包主體的創建方法,它實現上面所聲明的包定義
CREATE OR REPLACE PACKAGE BODY demo_pack
IS
--函數定義
FUNCTION add_dept(dept_no NUMBER, dept_name VARCHAR2, location VARCHAR2)
RETURN NUMBER
IS
empno_remaining EXCEPTION;
PRAGMA EXCEPTION_INIT(empno_remaining, -1);
/* -1 是違反唯一約束條件的錯誤代碼*/
BEGIN
INSERT INTO dept VALUES(dept_no, dept_name, location);
IF SQL%FOUND THEN
RETURN 1;
END IF;
EXCEPTION
WHEN empno_remaining THEN
RETURN 0;
WHEN OTHERS THEN
RETURN -1;
END add_dept;
--函數定義
FUNCTION remove_dept(dept_no NUMBER)
RETURN NUMBER
IS
BEGIN
DELETE FROM dept WHERE deptno=dept_no;
IF SQL%FOUND THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN -1;
END remove_dept;
--過程定義
PROCEDURE query_dept(dept_no IN NUMBER)
IS
BEGIN
SELECT * INTO DeptRec FROM dept WHERE deptno=dept_no;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('數據庫中沒有編碼爲'||dept_no||'的部門');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('程序運行錯誤!請使用遊標');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||’----‘||SQLERRM);
END query_dept;
BEGIN
Null;
END demo_pack;