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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章