一、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;