一、包
包是一組相關過程、函數、常量、變量、游標、異常等PL/SQL程序設計元素的組合。它類似於C++和Java中的類,其中變量相當於類中的成員變量,過程和函數相當於類中的方法。通過使用包,可以使開發人員利用面向對象的方法進行存儲過程的開發,從而提高系統的性能。
包的結構如下:
一個包由包頭和包主體組成:
包頭和包主體分開編譯,並作為兩個分開的對象存放在數據庫數據字典中。
包的大體語法如下:
包頭語法:
CREATE OR REPLACE PACKAGE 包名稱 IS
FUNCTION 函數名稱(參數 參數類型) RETURN 參數類型;
PROCEDURE 存儲過程名稱( 參數 輸入輸出類型 參數類型,參數 輸入輸出類型 參數類型) ;
end;
包體語法:
create or replace package body 包名稱 is
function 函數名稱(參數名稱 參數類型) return 參數類型 is
begin
處理語句
return 參數;
end;
procedure 存儲過程名稱( 參數 輸入輸出類型 參數類型,參數 輸入輸出類型 參數類型 ) is
begin
處理語句;
commit;
end;
end;
二、示例代碼
示例如下:
--包頭 CREATE OR REPLACE PACKAGE fkpackage IS v_comm NUMBER := 200 ; --每月獎金200 --定義結構體 type re_person is record( rid person.id%type, rusername person.username%type, rage person.age%type, rpassword person.password%type ); --定義游標 type t_person is ref cursor; --計算年薪的函數 FUNCTION get_year_sal (v_sal NUMBER) RETURN NUMBER ; --定義過程 PROCEDURE pro_person_add ( v_id NUMBER, v_username VARCHAR2, v_age NUMBER, v_password VARCHAR2 ) ; procedure get_person( v_id in number, c_person out t_person ); END fkpackage ; --包體 create or replace package body fkpackage is -- 函數 function get_year_sal (v_sal NUMBER) RETURN NUMBER IS BEGIN RETURN (v_sal + v_comm) * 12 ; END; --過程 procedure pro_person_add(v_id number, v_username varchar2, v_age number, v_password varchar2) is BEGIN INSERT INTO person VALUES (v_id, v_username, v_age, v_password); COMMIT; END; procedure get_person(v_id in number, c_person out t_person) is begin open c_person for select id,username,age,password from person; end; END;
調用代碼:
declare r_person fkpackage.t_person; --定義包中結構體變量 record_person fkpackage.re_person; v_id number; begin --使用及遍歷包中過程返回的結果集 dbms_output.put_line('年薪='||fkpackage.get_year_sal(12000)); v_id := 1; fkpackage.get_person(v_id, r_person); loop fetch r_person into record_person; exit when r_person%notfound; dbms_output.put_line('姓名='||record_person.rage); end loop; -- 添加數據 fkpackage.pro_person_add(10001, 'zhangsan', 20, '1343'); end;
三、 PL/SQL包的優點
包提供了幾個優點:模塊化、方便應用程序設計、信息隱藏、附加功能和良好的性能。
1、 模塊化
包能讓我們把邏輯相關的類型、常量、變量、異常和子程序等放到一個命名的PL/SQL模塊中。每一個包都容易理解,包與包之間接口簡單、清晰。這將有助於程序開發。
2、 輕松的程序設計 設計應用程序時,我們首先要確定的是包說明中的接口信息。我們可以在沒有包體的條件下編寫並編譯說明部分。然後引用該包的存儲子程序也會被編譯。在完成整個應用程序之前,我們是不需要完全實現包體部分的。
3、 信息隱藏
有了包,我們就可以指定哪些類型、常量、變量、異常和子程序等是公有(可見和可訪問)或私有(隱藏和不可訪問)。例如,如果一個包裡包含了四個子程 序,其中三個是公有的一個是私有的。包就會隱藏私有子程序的實現,這樣的話,如果實現內容發生改變,受到影響的只有包本身(不是我們的應用程序)。同樣, 對用戶隱藏實現細節也能保證包的完整性。
4、 附加功能
打包公有變量和游標在一個會話期會一直存在。所以,它們可以被當前環境下的所有子程序共享。並且它們允許我們跨事務來維護數據而不用把它保存在數據庫中。
5、 良好的性能
在我們首次調用打包子程序時,整個包就會被加載到內存中。所以,以後調用包中的相關子程序時,就不需要再次讀取磁盤了。包能阻塞級聯依賴,這樣就能避免不必要的編譯。例如,如果我們改變打包函數的實現,Oracle不需要重新編譯調用子程序,因為它們並不依賴於包體。
四、系統中的包
Oracle和各種Oracle工具都提供了系統包來幫助我們建立基於PL/SQL的應用程序。下面介紹一下其中比較典型的包。
1、 關於DBMS_ALERT包
DBMS_ALERT能讓數據庫觸發器在特定的數據庫值發生變化時向應用程序發送報警。報警是基於事務的並且是異步的(也就是它們的操作與定時機制無關)。例如,當新的股票和債券上市時公司就可以通過這個包更新來他的投資總額。
2、 關於DBMS_OUTPUT包
包DBMS_OUTPUT能讓我們顯示來自PL/SQL塊和子程序中的輸出內容,這樣就會很容易地進行測試和調試。過程put_line能把信息輸 出到SGA的一個緩存中。我們可以通過調用過程get_line或在SQL*Plus中設置SERVEROUTPUT ON就能顯示這些信息。
3、 關於DBMS_PIPE包
包DBMS_PIPE允許不同的會話通過命名管道來進行通信(管道就是一塊內存區域,進程使用這個區域把消息傳遞給另外一個進程)。我們可以使用過 程pack_message和send_message把消息封裝到一個管道,然後把消息發送到同一個實例中的另一個會話中。 管道的另一個終端,我們可以使用過程recieve_message和unpack_message來接受並打開要讀取的消息。命名管道在很多地方都很有用。例如,我們可以用C語言編寫一個收集信息的程序,然後把信息通過管道傳遞給存儲過程。
4、關於UTL_FILE包
包UTL_FILE能讓我們的PL/SQL程序讀寫操作系統(OS)文本文件。它提供了標准的OS流文件I/O,包括open、put、get和close操作。當我們想要讀寫文件的時候,我們可以調用函數fopen,它能返回一個在後續過程調用中使用到的文件句柄。例如,過程put_line能往打開的文件中寫入文本字符串,並在後邊添加一個換行符,過程get_line能從打開的文件讀取一行內容到放到一個輸出緩存中。
5、關於UTL_HTTP包
包UTL_HTTP可以讓我們PL/SQL程序使用超文本傳輸協議(HTTP)進行通信。它可以從互聯網接收數據或調用Oracle Web服務器的cartridge。這個包有兩個入口點,每一個都接受一個URL(統一資源定位器)字符串,然後連接到一個指定的網站並返回所請求的數 據,這些數據通常是超文本標記語言HTML格式。
1、創建包體和包規范的代碼要分開執行,不要一起執行。
2、解決辦法:先執行
create or replace package pack is
....
end pack;
/
再執行
create or replace package body pack is
....
end;
/
---
以上,希望對你有所幫助。
Create Table emp (employee_id Number,salary Number,commission_pct Number)
建了表測試了一下沒問題的,
第一個過程是更新工資
第二個函數是返回年薪,有結果。在output界面有結果