一、PL/SQL包概述
1. 什麼是PL/SQL包:
相關元件的組合:PL/SQL型別、變數,資料結構,和表示式、子程式: 過程和函式
2. 包的組成部分:
由兩部分組成:
包頭
包體
3. 包的優點
一次讀取多個物件進入記憶體
二、PL/SQL包的元件
包頭:公共部分:包內和包外的程式都可以訪問
包體:私有部分:包體定義的變數或者程式只能被本包內的程式呼叫
1. 建立包頭
語法:
CREATE [OR REPLACE] PACKAGE package_name IS|AS
public type and variable declarations
subprogram specifications
END [package_name];
OR REPLACE選項刪除並且重新建立包
在包頭宣告的變數初始化值預設為NULL
所有在包頭宣告的結構,對於所有授予該包許可權的使用者都是可見的
包宣告示例: comm_pkg
CREATE OR REPLACE PACKAGE comm_pkg IS
std_comm NUMBER := 0.10; --initialized to 0.10
PROCEDURE reset_comm(new_comm NUMBER);
END comm_pkg;
/ STD_COMM 是一個全域性變數,初始為0. RESET_COMM 用於重新設定獎金的過程,它在包體中被定義
2. 建立包體
語法:
CREATE [OR REPLACE] PACKAGE BODY package_name IS|AS
private type and variable declarations
subprogram bodies
[BEGIN initialization statements]
END [package_name];
OR REPLACE選項刪除並且重新重建包體
包體中定義的識別符號是私有的,包體之外不可見
所有的私有結構,在引用前必須先宣告
公共結構在包體中是可見的
create or replace package comm_pkg is
std_comm number := 0.10;
procedure reset_comm(new_comm number);
end; create or replace package body comm_pkg is
function validate(comm number) return boolean is
max_comm employees.commission_pct%type;
begin
select max(commission_pct) into max_comm from employees;
return(comm between and max_comm);
end validate; procedure reset_comm(new_comm number) is
begin
if validate(new_comm) then
std_comm := new_comm;
else
raise_application_error(-, 'Bad Commission');
end if;
end reset_comm;
end;
三、呼叫包中的子程式
在同一個包內呼叫子程式:
CREATE OR REPLACE PACKAGE BODY comm_pkg IS ...
PROCEDURE reset_comm(new_comm NUMBER) IS
BEGIN
IF validate(new_comm) THEN
std_comm := new_comm;
ELSE ...
END IF;
END reset_comm;
END comm_pkg;
在sqlplus中呼叫包中的過程:
SQL> execute comm_pkg.reset_comm(0.15);
SQL> set serveroutput on;
SQL> ed declare
v_std_comm comm_pkg.std_comm%type;
begin
v_std_comm := comm_pkg.std_comm;
dbms_output.put_line(v_std_comm);
end;
/ 結果:
SQL> /
std_comm:.
PL/SQL procedure successfully completed
在不同模式下呼叫包內的過程
SQL> conn hr/hr SQL> grant execute on comm_pkg to scott; conn scott/tiger SQL> execute comm_pkg.reset_comm(0.36);
PL/SQL procedure successfully completed SQL>
SQL> declare
v_std_comm comm_pkg.std_comm%type;
begin
v_std_comm := comm_pkg.std_comm;
dbms_output.put_line('v_std_comm:' || v_std_comm||'std_comm:' || comm_pkg.std_comm);
end;
/
v_std_comm:.36std_comm:.
PL/SQL procedure successfully completed
注意:千萬不要在sql視窗中寫入這段話,不然執行過程是在sql中執行,全域性變數存在於sql程序中嗎,不會存在sql視窗中,所以在sql視窗中訪問到的永遠都是std_comm的初始值:0.10
四、建立和使用無體包
create or replace package global_consts is
mile_2_kilo CONSTANT NUMBER := 1.6093;
kilo_2_mile CONSTANT NUMBER := 0.6214;
yard_2_meter CONSTANT NUMBER := 0.9144;
meter_2_yard CONSTANT NUMBER := 1.0936;
end;
無體包內宣告的變數時全域性變數,包外的子程式或者匿名塊都可以使用
在匿名塊中使用:
BEGIN
DBMS_OUTPUT.PUT_LINE('20 miles = ' || * global_consts.mile_2_kilo ||
' km');
END;
在子程式中呼叫:
CREATE FUNCTION mtr2yrd(m NUMBER) RETURN NUMBER IS
BEGIN
RETURN(m * global_consts.meter_2_yard);
END mtr2yrd; begin
DBMS_OUTPUT.PUT_LINE(mtr2yrd());
end;
五、在資料字典中檢視包的資訊
檢視包頭資訊:
SELECT text
FROM user_source
WHERE name = 'COMM_PKG'
AND type = 'PACKAGE';
檢視包體資訊:
SELECT text
FROM user_source
WHERE name = 'COMM_PKG'
AND type = 'PACKAGE BODY';
六、使用包的優勢
1. 模組化: 封裝相關的結構
2. 更加容易維護: 將相關的邏輯功能組合到一起
3. 使應用設計更加容易: 包頭和包體的編譯是分開進行的
4. 隱藏資訊:
對於應用,只有宣告部分是可見的
包體的私有部分被隱藏並且不能被應用訪問
包體中的所有程式碼被隱藏
5. 提高了效能:
當包第一次被引用的時候,包內的所有內容全部被載入到記憶體中
對於所有的使用者來講,在記憶體中只複製一次
簡化了依賴性
6. 過載: 多個子程式相同的名
七、刪除包
使用如下語法刪除包頭和包體:
DROP PACKAGE package_name; 刪除包體語法: DROP PACKAGE BODY package_name;