📄 第九章 pl-sql包 - pl-sql用户指南与参考 - whatiswhat.htm
字号:
color=#295200><B>第九章 PL/SQL包</B></FONT>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#a5bd6b cellSpacing=1
cellPadding=0 width="100%" border=1>
<TBODY>
<TR>
<TD align=middle>
<TABLE style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word"
cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD align=middle>
<TABLE
style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word"
cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<DIV id=art style="MARGIN: 15px">
<DIV class=postTitle><A class=postTitle2
id=AjaxHolder_ctl01_TitleUrl
href="http://www.cnblogs.com/cxd4321/archive/2008/03/19/1113191.html">第九章
PL/SQL包</A> </DIV>
<P class=title1>一、什么是PL/SQL包</P>
<P>包就是一个把各种逻辑相关的类型、常量、变量、异常和子程序组合在一起的模式对象。包通常由两个部分组成:包说明和包体,但有时包体是不需要的。说明(简写为spec)是应用程序接口;它声明了可用的类型、变量、常量、异常、游标和子程序,包体部分完全定义游标和子程序,并对说明中的内容加以实现。
</P>
<P>如下例所示,我们可以认为说明部分是一个可选接口,而包体是一个"黑盒"。我们可以调试、增强或替换一个包体而不同改变接口(包说明)。
</P><IMG alt=""
src="第九章 PL-SQL包 - PL-SQL用户指南与参考 - whatiswhat.files/o_9-1.gif">
<P>我们可以从SQL*Plus中使用CREATE PACKAGE语句来创建一个包。语法如下:</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>CREATE</STRONG> [<STRONG>OR</STRONG> REPLACE] <STRONG>PACKAGE</STRONG> package_name<BR> [<STRONG>AUTHID</STRONG> {CURRENT_USER | DEFINER}]<BR> {<STRONG>IS</STRONG> | <STRONG>AS</STRONG>}<BR> [<STRONG>PRAGMA</STRONG> SERIALLY_REUSABLE;]<BR> [collection_type_definition ...]<BR> [record_type_definition ...]<BR> [subtype_definition ...]<BR> [collection_declaration ...]<BR> [constant_declaration ...]<BR> [exception_declaration ...]<BR> [object_declaration ...]<BR> [record_declaration ...]<BR> [variable_declaration ...]<BR> [cursor_spec ...]<BR> [function_spec ...]<BR> [procedure_spec ...]<BR> [call_spec ...]<BR> [<STRONG>PRAGMA</STRONG> RESTRICT_REFERENCES(assertions) ...]<BR><STRONG>END</STRONG> [package_name];<BR><BR>[<STRONG>CREATE</STRONG> [<STRONG>OR</STRONG> REPLACE] <STRONG>PACKAGE</STRONG> <STRONG>BODY</STRONG> package_name {<STRONG>IS</STRONG> | <STRONG>AS</STRONG>}<BR> [<STRONG>PRAGMA</STRONG> SERIALLY_REUSABLE;]<BR> [collection_type_definition ...]<BR> [record_type_definition ...]<BR> [subtype_definition ...]<BR> [collection_declaration ...]<BR> [constant_declaration ...]<BR> [exception_declaration ...]<BR> [object_declaration ...]<BR> [record_declaration ...]<BR> [variable_declaration ...]<BR> [cursor_body ...]<BR> [function_spec ...]<BR> [procedure_spec ...]<BR> [call_spec ...]<BR>[<STRONG>BEGIN</STRONG><BR> sequence_of_statements]<BR><STRONG>END</STRONG> [package_name];]
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>在说明部分声明的内容都是公有的,对应用程序是可见的。我们必须在所有的其他内容(除了用于为一个特殊的函数命名的编译指示;这样的编译指示必须跟在函数说明之后)声明之后才可以声明子程序。</P>
<P>包体中的内容有私有的,它实现了说明部分定义的细节内容,并且对应用程序是不可见的。紧跟着包体声明部分的是一个可选的初始化部分,它用于初始化包中的变量等。
</P>
<P>AUTHID语句决定了是否是所有的打包子程序都按定义者权限(默认)或调用者权限执行,其中涉及到的模式对象是在定义者的模式中解析还是在调用者的模式中解析。
</P>
<P>一个调用说明能让我们在Oracle数据词典中发布一个Java方法或外部C函数。调用说明靠把程序的名称、参数类型和返回类型映射到它们的SQL副本(SQL
counterpart)中来发布程序。 </P>
<P class=title2>1、PL/SQL包举例</P>
<P>在下面的例子中,我们把一个记录类型、游标和两个employment过程进行打包。要注意,过程hire_employee使用数据库序列empno_seq和函数SYSDATE分别插入到字段雇员编号和雇佣日期。
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>CREATE</STRONG> <STRONG>OR</STRONG> REPLACE <STRONG>PACKAGE</STRONG> emp_actions <STRONG>AS</STRONG> <EM>-- spec</EM><BR> <STRONG>TYPE</STRONG> emprectyp <STRONG>IS</STRONG> <STRONG>RECORD</STRONG>(<BR> emp_id INT,<BR> salary <STRONG>REAL</STRONG><BR> );<BR><BR> <STRONG>CURSOR</STRONG> desc_salary <STRONG>RETURN</STRONG> emprectyp;<BR><BR> <STRONG>PROCEDURE</STRONG> hire_employee(<BR> ename <STRONG>VARCHAR2</STRONG>,<BR> job <STRONG>VARCHAR2</STRONG>,<BR> mgr <STRONG>NUMBER</STRONG>,<BR> sal <STRONG>NUMBER</STRONG>,<BR> comm <STRONG>NUMBER</STRONG>,<BR> deptno <STRONG>NUMBER</STRONG><BR> );<BR><BR> <STRONG>PROCEDURE</STRONG> fire_employee(emp_id <STRONG>NUMBER</STRONG>);<BR><STRONG>END</STRONG> emp_actions;<BR><BR><STRONG>CREATE</STRONG> <STRONG>OR</STRONG> REPLACE <STRONG>PACKAGE</STRONG> <STRONG>BODY</STRONG> emp_actions <STRONG>AS</STRONG> <EM>-- body</EM><BR> <STRONG>CURSOR</STRONG> desc_salary <STRONG>RETURN</STRONG> emprectyp <STRONG>IS</STRONG><BR> <STRONG>SELECT</STRONG> empno, sal<BR> <STRONG>FROM</STRONG> emp<BR> <STRONG>ORDER</STRONG> <STRONG>BY</STRONG> sal <STRONG>DESC</STRONG>;<BR><BR> <STRONG>PROCEDURE</STRONG> hire_employee(<BR> ename <STRONG>VARCHAR2</STRONG>,<BR> job <STRONG>VARCHAR2</STRONG>,<BR> mgr <STRONG>NUMBER</STRONG>,<BR> sal <STRONG>NUMBER</STRONG>,<BR> comm <STRONG>NUMBER</STRONG>,<BR> deptno <STRONG>NUMBER</STRONG><BR> ) <STRONG>IS</STRONG><BR> <STRONG>BEGIN</STRONG><BR> <STRONG>INSERT</STRONG> <STRONG>INTO</STRONG> emp<BR> <STRONG>VALUES</STRONG> (empno_seq.<STRONG>NEXTVAL</STRONG>,<BR> ename,<BR> job,<BR> mgr,<BR> <STRONG>SYSDATE</STRONG>,<BR> sal,<BR> comm,<BR> deptno);<BR> <STRONG>END</STRONG> hire_employee;<BR><BR> <STRONG>PROCEDURE</STRONG> fire_employee(emp_id <STRONG>NUMBER</STRONG>) <STRONG>IS</STRONG><BR> <STRONG>BEGIN</STRONG><BR> <STRONG>DELETE</STRONG> <STRONG>FROM</STRONG> emp<BR> <STRONG>WHERE</STRONG> empno = emp_id;<BR> <STRONG>END</STRONG> fire_employee;<BR><STRONG>END</STRONG> emp_actions; </TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>只有在包说明部分的声明内容对应用程序才是可见可访问的;包体的详细实现是不可见不可访问的。所以,我们可以在不重新编译调用程序的前提下修改包体(实现)。
</P>
<P
class=title1>二、PL/SQL包的优点</P>包提供了几个优点:模块化、方便应用程序设计、信息隐藏、附加功能和良好的性能。
<UL>
<LI>模块化 </LI></UL>
<P>包能让我们把逻辑相关的类型、常量、变量、异常和子程序等放到一个命名的PL/SQL模块中。每一个包都容易理解,包与包之间接口简单、清晰。这将有助于程序开发。
</P>
<UL>
<LI>轻松的程序设计 </LI></UL>
<P>设计应用程序时,我们首先要确定的是包说明中的接口信息。我们可以在没有包体的条件下编写并编译说明部分。然后引用该包的存储子程序也会被编译。在完成整个应用程序之前,我们是不需要完全实现包体部分的。
</P>
<UL>
<LI>信息隐藏 </LI></UL>
<P>有了包,我们就可以指定哪些类型、常量、变量、异常和子程序等是公有(可见和可访问)或私有(隐藏和不可访问)。例如,如果一个包里包含了四个子程序,其中三个是公有的一个是私有的。包就会隐藏私有子程序的实现,这样的话,如果实现内容发生改变,受到影响的只有包本身(不是我们的应用程序)。同样,对用户隐藏实现细节也能保证包的完整性。
</P>
<UL>
<LI>附加功能 </LI></UL>
<P>打包公有变量和游标在一个会话期会一直存在。所以,它们可以被当前环境下的所有子程序共享。并且它们允许我们跨事务来维护数据而不用把它保存在数据库中。
</P>
<UL>
<LI>良好的性能 </LI></UL>
<P>在我们首次调用打包子程序时,整个包就会被加载到内存中。所以,以后调用包中的相关子程序时,就不需要再次读取磁盘了。包能阻塞级联依赖,这样就能避免不必要的编译。例如,如果我们改变打包函数的实现,Oracle不需要重新编译调用子程序,因为它们并不依赖于包体。
</P>
<P class=title1>三、理解包说明</P>
<P>包说明包括了公有声明。这些声明的作用于对于数据库模式来说是本地的,对于包来说是全局的。所以,被声明的内容可以从应用程序中和包的任何地方访问。下图演示了包的作用范围:
</P><IMG alt=""
src="第九章 PL-SQL包 - PL-SQL用户指南与参考 - whatiswhat.files/o_9-2.gif">
<P>说明中列出了包中对应用程序所有可用的资源。例如,下面的声明演示了一个接受INTEGER类型的参数并返回一个INTEGER结果的函数fac:
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>FUNCTION</STRONG> fac (n <STRONG>INTEGER</STRONG>) <STRONG>RETURN</STRONG> <STRONG>INTEGER</STRONG>; <EM>-- returns n!</EM>
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>这些就是我们要调用的函数的所有信息。我们并不需要考虑它的实现细节(如,是使用迭代还是递归)。</P>
<P>只有子程序和游标有实现部分。所以,如果一个说明只有类型、常量、变量、异常的声明和调用说明,那么包体就没有必要的了。下面就是一个没有包体的包:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -