Oracle 中包(Package)


一、什么要使用包?

       在一個大型項目中,可能有很多模塊,而每個模塊又有自己的過程、函數等。而這些過程、函數默認是放在一起的(如在PL/SQL中,過程默認都是放在一起 的,即Procedures中),這些非常不方便查詢和維護,甚至會發生誤刪除的事件。

PL/SQL為了滿足程序模塊化的需要,引入了包的構造。通過使用包就可以分類管理過程和函數等。

(1)包是一種數據庫對象,相當於一個容器。將邏輯上相關的過程、函數、變量、常量和游標組合成一個更大的單位。用戶可以從其他 PL/SQL 塊中對其進行引用

(2)包類似於C++和JAVA語言中的類,其中變量相當於類中的成員變量,過程和函數相當於類方法。把相關的模塊歸類成為包,可使開發人員利用面向對象的方法進行開發,具有面向對象程序設計語言的特點,

(4)PL/SQL的包具有信息隱蔽性(information hiding),僅在算法和數據結構設計有關層可見。可將過程說明和過程體組成一個程序單位。也可將過程說明與它的過程體分開。也可在包中定義過程,而該過程在包說明中沒有定義過程說明,這樣定義的過程僅在包內使用。

(5)在PL/SQL程序設計中,使用包不僅可以使程序設計模塊化,對外隱藏包內所使用的信息(通過使用私用變量),而寫可以提高程序的執行效率。因為,當程序首次調用包內函數或過程時,ORACLE將整個包調入內存,當再次訪問包內元素時,ORACLE直接從內存中讀取,而不需要進行磁盤I/O操作,從而使程序執行效率得到提高。

二、包結構

一個包由兩個分開的部分組成:包規范包體

2.1包定義(PACKAGE)

(1) 包定義(PACKAGE):包定義部分是為應用程序的接口,聲明包內數據類型、變量、常量、游標、子程序和異常錯誤處理等元素,這些元素為包的公有元素。

CREATE [OR REPLACE] PACKAGE package_name
 
  {IS | AS}

   [公有數據類型定義]

   [公有游標聲明]

   [公有變量、常量聲明]

   [公有子程序聲明]

END   [package_name];

2.2包主體(PACKAGE BODY)

包主體(PACKAGE BODY):包主體則是包定義部分的具體實現,它定義了包定義部分所聲明的游標和子程序,在包主體中還可以聲明包的私有元素。如果在包主體中的游標或子程序並沒有在包頭中定義,那么這個游標或子程序是私有的。

CREATE [OR REPLACE] PACKAGE BODY package_name

{IS | AS}

                   [私有數據類型定義]

                   [私有變量、常量聲明]

                   [私有子程序聲明和定義]

                   [公有子程序定義]

BEGIN

                   執行部分(初始化部分)

END [package_name];

與類相同,包中的程序元素也分為公用元素和私用元素兩種,這兩種元素的區別是他們允許訪問的程序范圍不同,即它們的作用域不同。公用元素不僅可以被包中的函數、過程所調用,也可以被包外的PL/SQL程序訪問,而私有元素只能被包內的函數和過程序所訪問。

包定義和包主體分開編譯,並作為兩部分分開的對象存放在數據庫字典中。包定義一定要在包主體前面編譯,包主體可以沒有,但包定義一定要有) 包的名稱和包體的名稱要保持一致

三、包舉例

定義包規范

CREATE OR REPLACE 
package p_stu
as
    --定義結構體
    type re_stu is record(
        rname student.name%type,
        rage  student.age%type
    );
    --定義游標
    type c_stu is ref cursor;
    --定義函數
    function numAdd(num1 number,num2 number)return number;
    --定義過程
    procedure GetStuList(cid in varchar2,c_st out c_stu); 
end;

說明 type c_stu is ref cursor;

type c_stu:定義類型變量

is ref cursor:相當於數據類型,不過是引用游標的數據類型clip_image002

這種變量通常用於存儲過程和函數返回結果集時使用,因為PL/SQL不允許存儲過程或函數直接返回結果集,但可以返回類型變量,於是引用游標的類型變量作為輸出參數或返回值就應運而生了。

定義包體:

CREATE OR REPLACE 
package body p_stu
as
    --游標和結構體,包規范中已聲明,包體中不用再聲明,直接使用。
    
    --實現方法   
    function numAdd(num1 number,num2 number)return number
    as
        num number;
    begin
        num:=num1+num2;
        return num;
    end;
    
    --實現過程
    procedure GetStuList(cid varchar2,c_st out c_stu)
    as
        r_stu re_stu; --直接使用包規范中的結構
    begin
        open c_st for select name,age from student where classid=cid;
       -- 如果已經在過程中遍歷了游標,在使用這個過程的塊中,將沒有值。
       -- loop
       --     fetch c_st into r_stu;  
       --     exit when c_st%notfound;
       --     dbms_output.put_line('姓名='||r_stu.rname);
       -- end loop;
    end;
end;

調用包

declare
    c_stu p_stu.c_stu;   --定義包中游標變量
    r_stu p_stu.re_stu;  --定義包中結構體變量
    num number;
begin
    --使用及遍歷包中過程返回的結果集
    p_stu.GetStuList('5',c_stu);
    loop
        fetch c_stu into r_stu;
        exit when c_stu%notfound;
        dbms_output.put_line('姓名='||r_stu.rname);
    end loop;
    
    --使用包中的方法
    select p_stu.numAdd(5,6) into num from dual;
    dbms_output.put_line('Num='||num);
end;

參考

Oracle 包(Package)

第七章 程序包的創建和應用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM