CREATE PACKAGE定義一個包。CREATE OR REPLACE PACKAGE將會建立一個新包或者替換一個已有的定義。包是組織和封裝資料庫應用程式邏輯的重要工具。通過合理設計和使用包,可以提高代碼的可維護性、重用性和效能。
簡介
CREATE PACKAGE語句用於建立儲存包的規範,儲存包是儲存在資料庫中的相關過程、函數及其他程式對象的封裝集合。包規範聲明了這些對象,而隨後的包體則定義了這些對象的具體實現。
如果建立包時包含schema名稱,則將在指定的schema中建立。否則,將在當前schema中建立。除非要更新現有包的定義,否則新包的名稱不能與同一schema中的任何現有包匹配。在這種情況下,請使用CREATE OR REPLACE PACKAGE。建立該過程的使用者將成為包的所有者。
包是將過程和函數建立為獨立模組對象的替代方案。
文法
CREATE [ OR REPLACE ] PACKAGE <package_name>
[ AUTHID { DEFINER | CURRENT_USER } ]
{ IS | AS }
[ <declaration>; ] [, ...]
[ {
PROCEDURE <proc_name>
[ (<argname> [ IN | IN OUT | OUT ] <argtype> [ DEFAULT <value> ]
[, ...]) ];
[ PRAGMA RESTRICT_REFERENCES(<proc_name>,
{ RNDS | RNPS | TRUST | WNDS | WNPS } [, ... ] ); ]
|
FUNCTION <func_name>
[ (<argname> [ IN | IN OUT | OUT ] <argtype> [ DEFAULT <value> ]
[, ...]) ]
RETURN <rettype> [ DETERMINISTIC ];
[ PRAGMA RESTRICT_REFERENCES(<func_name>,
{ RNDS | RNPS | TRUST | WNDS | WNPS } [, ... ] ); ]
}
] [, ...]
END [ <name> ]參數說明
參數 | 描述 |
package_name | 要建立的包的名稱(可選 |
DEFINER | CURRENT_USER | 指定使用何種許可權訪問包中引用的資料庫物件。取值範圍如下:
|
declaration | 公開變數、類型、遊標或 |
proc_name | 公用預存程序名稱。 |
argname | 參數名稱。 |
IN | IN OUT | OUT | 參數模式。 |
argtype | 程式參數的資料類型。 |
DEFAULT value | 輸入參數的預設值。 |
func_name | 公用函數名稱。 |
rettype | 返回資料類型。 |
DEFERMININTIC |
|
RNDS | RNPS | TRUST | WNDS | WNPS | 為實現相容性提供該參數,請忽略。 |
結構
包頭定義了包的介面部分,包括公開的常量、變數、類型、過程和函數等。其他程式單元可以引用包頭中聲明的對象。
CREATE OR REPLACE PACKAGE Employee_Pkg AS
-- 常量
MAX_SALARY CONSTANT NUMBER := 100000;
-- 過程聲明
PROCEDURE Add_Employee(
p_emp_id IN NUMBER,
p_first_name IN VARCHAR2,
p_last_name IN VARCHAR2,
p_salary IN NUMBER
);
PROCEDURE Update_Salary(
p_emp_id IN NUMBER,
p_new_salary IN NUMBER
);
-- 函式宣告
FUNCTION Get_Employee_Name(
p_emp_id IN NUMBER
) RETURN VARCHAR2;
END Employee_Pkg;注意事項
依賴管理:修改包頭會導致依賴包的所有對象需要重新編譯,請謹慎進行變更。
錯誤處理:在包中妥善處理異常,避免未捕獲的異常導致程式中斷。
效能最佳化:合理使用包的私人變數和緩衝機制,提高效能。
安全性:通過包的許可權控制限制對敏感性資料和功能的訪問。
命名規範:遵循統一的命名規範,便於代碼理解和維護。
使用說明
一旦包成功建立並編譯完成,即可在PL/SQL代碼中引用包內的過程、函數等。
調用包中的過程和函數
調用過程。
BEGIN Employee_Pkg.Add_Employee( p_emp_id => 1001, p_first_name => '張', p_last_name => '三', p_salary => 50000 ); END;調用函數
DECLARE v_emp_name VARCHAR2(100); BEGIN v_emp_name := Employee_Pkg.Get_Employee_Name(1001); DBMS_OUTPUT.PUT_LINE('員工姓名: ' || v_emp_name); END;
包同名函數處理
Oracle支援包中的同名函數,實作類別似多態的行為,對應的PolarDB也支援相同的行為。
PolarDB PostgreSQL版Oracle文法相容 2.0在核心小版本2.0.14.26.0新增建立IN參數相同,OUT參數不同的同名函數。若叢集的核心小版本低於該版本且需要使用該功能,請將核心小版本升級到2.0.14.26.0或以上版本。查詢和升級核心小版本,請參見版本管理。
CREATE OR REPLACE PACKAGE Employee_Pkg AS
-- 常量
MAX_SALARY CONSTANT NUMBER := 100000;
-- 函式宣告
FUNCTION Get_Employee_Name(
p_emp_id IN NUMBER
) RETURN VARCHAR2;
-- 同名函數
FUNCTION Get_Employee_Name(
p_emp_id IN NUMBER,
res_info OUT text
) RETURN VARCHAR2;
END Employee_Pkg;包函數使用包變數作為參數預設值
PolarDB PostgreSQL版Oracle文法相容 2.0在核心小版本2.0.14.26.0新增使用包變數做函數參數預設值。若叢集的核心小版本低於該版本且需要使用該功能,請將核心小版本升級到2.0.14.26.0或以上版本。查詢和升級核心小版本,請參見版本管理。
CREATE OR REPLACE PACKAGE test_package AS
a NUMBER := 1;
b NUMBER := 2;
END my_package;
CREATE OR REPLACE PACKAGE my_package AS
FUNCTION add_numbers(x NUMBER default test_package.a, y NUMBER default test_package.b) RETURN NUMBER;
PROCEDURE print_message(msg VARCHAR2);
END my_package;維護和更新包
如需向包中添加新的公開對象,必須對包頭和包體進行相應的修改。修改包頭將導致依賴該包的所有對象失效,需要重新進行編譯。如果僅對包體中的實現進行修改(不影響包頭),則無需重新編譯依賴對象。詳細的包體SQL語句介紹請參考CREATE PACKAGE BODY。
向包中添加新函數。
修改包頭。
CREATE OR REPLACE PACKAGE Employee_Pkg AS -- 現有聲明 FUNCTION Get_Employee_Department(p_emp_id IN NUMBER) RETURN VARCHAR2; END Employee_Pkg;修改包體。
CREATE OR REPLACE PACKAGE BODY Employee_Pkg AS -- 現有實現 FUNCTION Get_Employee_Department(p_emp_id IN NUMBER) RETURN VARCHAR2 IS v_department VARCHAR2(100); BEGIN SELECT department INTO v_department FROM employees WHERE emp_id = p_emp_id; RETURN v_department; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 'Not Assigned'; END Get_Employee_Department; END Employee_Pkg;
相關參考
完整的包建立和使用樣本請參考樣本。