Oracle PL/SQL進階編程(第四彈:理解PL/SQL包)

什麼是包

一個PL/SQL包由兩部分組成:
- 包規範:主要是包的一些定義信息,不包含具體的代碼實現,是PL/SQL程序的接口部分,包含類型、記錄、變量、常量、異常定義、遊標和子程序的聲明。
- 包體:包體是對包規範中聲明的子程序的實現部分,包體的內容對於外部應用程序來說是不可見的。

包的優點

  • 模塊化設計。
  • 規範化的程序設計。
  • 實現信息的隱藏。
  • 提供全局共享的附加功能:在包中公開的變量或遊標在一個會話期會一直存在,並且可以被當前環境下的所有子程序共享,因此可以將包中定義的變量當做全局變量來使用,並且可以跨事務來維護數據而不用把它保存在數據庫中。
  • 提供了良好的性能體驗:由於在首次打開包子程序時,整個包都會被加載到內存中,後續的調用只需要從內存中讀取而不需要再次讀取磁盤。

定義包規範

代碼如下:

--定義包規範,包規範將被用於應用程序的接口部分,供外部調用
CREATE OR REPLACE PACKAGE emp_pkg AS
   --定義集合類型
   TYPE emp_tab IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
   --在包規範中定義一個記錄類型
   TYPE emprectyp IS RECORD(
      emp_no NUMBER,
      sal  NUMBER
   );
   --定義一個遊標變量
   CURSOR desc_salary RETURN emprectyp;
   --定義僱傭員工的過程
   PROCEDURE hire_employee(p_empno NUMBER,p_ename VARCHAR2,p_job VARCHAR2,p_mgr NUMBER,p_sal NUMBER,
                        p_comm NUMBER,p_deptno NUMBER,p_hiredate DATE);
   --定義解僱員工的過程                        
   PROCEDURE fire_employee(p_emp_id NUMBER );
END emp_pkg;

定義包體

代碼如下:

--定義包體
CREATE OR REPLACE PACKAGE BODY emp_pkg
AS
   --定義遊標變量的具體類型
   CURSOR desc_salary RETURN emprectyp IS
      SELECT empno, sal FROM emp ORDER BY sal DESC;
   --定義僱傭員工的具體實現
   PROCEDURE hire_employee(p_empno NUMBER,p_ename VARCHAR2,
                           p_job VARCHAR2,p_mgr NUMBER,p_sal NUMBER,
                           p_comm NUMBER,p_deptno NUMBER,p_hiredate DATE) IS
   BEGIN
      --向emp表中插入一條員工信息
      INSERT INTO emp VALUES(p_empno,p_ename,p_job,p_mgr,p_hiredate,p_sal,p_comm,p_deptno); 
   END;       
   --定義解僱員工的具體實現                 
   PROCEDURE fire_employee(p_emp_id NUMBER ) IS
   BEGIN
      --從emp表中刪除員工信息
      DELETE FROM emp WHERE empno=p_emp_id;
   END;          
END emp_pkg;

調用包組件

當包被第一次調用時,將進行初始化,比如將包從硬盤上調到內存中來,放到系統全局工作區的共享緩衝池中,包的運行狀態則被放入用戶全局區的會話存儲區中。因此可以保證每個調用報的會話都擁有包的運行副本,當會話結束時,包的運行狀態纔會被釋放。因此包中的變量具有會話級的作用域,因而可以跨多個事務存儲數據。

包的這種特性使得我們可以在包中保存跨多個事務的數據,這大大方便了複雜的程序邏輯的中間數據的存儲,而不用特意用一個表來存儲臨時的數據。

如果在定義包規範時,指定了編譯提示SERIALLY_REUSABLE,則可以將包的運行狀態保存在系統全局工作區,而不是用戶全局區,這樣每次調用包以後,包的運行狀態就會被釋放,這樣再次調用包時,將重新開始包的狀態。
PRAGMA SERIALLY_REUSABLE;
不過這種每次調用便釋放的連續進行會佔用大量的內存,內存的佔用量與包的併發調用用戶數成正比,而與當前登錄的用戶數無關,因此需要謹慎使用。

編譯和調試包

可以使用PL/SQL Developer的調試功能進行可視化的調試和編譯,也可以使用ALTER PACKAGE語句來重新編譯包。

ALTER PACKAGE emp_pkg COMPILE BODY;           --編譯包體
ALTER PACKAGE emp_pkg COMPILE PACKAGE;        --編譯包規範和包體
ALTER PACKAGE emp_pkg COMPILE SPECIFICATION;  --編譯包規範

顯式地對包進行重新編譯可以清楚運行階段的隱式編譯,這樣可以防止在運行時的編譯錯誤及所帶來的性能開銷。

查看包的源代碼

與子程序一樣,可以查詢user_objects視圖來查看數據字典中包含的包的信息。

 SELECT object_type, object_name, status
  FROM user_objects
  WHERE object_type IN ('PACKAGE', 'PACKAGE BODY');

也可以從user_source視圖中獲取包的源代碼,

SELECT line, text
  FROM user_source
 WHERE NAME = 'EMP_ACTION_PKG' AND TYPE = 'PACKAGE'
ORDER BY line;

SELECT line, text
  FROM user_source
 WHERE NAME = 'EMP_ACTION_PKG' AND TYPE = 'PACKAGE BODY'
ORDER BY line;
發佈了165 篇原創文章 · 獲贊 47 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章