Oracle Package
(转自:http://blog.csdn.net/bbliutao/article/details/9016947)
一、概述
包可将一些有联系的对象放在其内部。
任何能在块定义部分出现的对象都可以在包中出现。这些对象包括存储过程、函数、游标、自定义的类型和变量。
我们可以在其它的PLSQL块中引用包中的这些对象,也就是说,包为PLSQL提供了全局变量。
包可以实现信息屏蔽和子程序重载。
二、包的定义
一个包由两个独立部分组成——包头和包体,各部分被单独存放在数据字典中,定义一个包,要分别定义包头和包体。
1、定义包头
(1)、语法:
create or replace package [schema.] package_name {is|as}
pl/sql_package;
其中package_name是包的名称,pl/sql_package可以是存储过程、函数、变量、类型、异常及游标的定义。
存储过程和函数必须在包头中预定义。也就是说,在包头中仅定义存储过程名或函数名以及它们的参数,
存储过程或函数的执行代码将在包体中定义,这不同于无名块中定义存储过程和函数。
例一:
create or replace package aupack as
procedure qusalary(p_code auths.code%type,p_salary out auths.salary%type);
procedure inauthor(p_code auths.code%type,p_salary out auths.salary%type);
end aupack;
2、定义包体
包体是有个数据字典对象。只有在包头成功编译后,包体才能被编译。包体只包含包头中已预定义的子程序代码。
在包头中定义(不是预定义)的对象可以直接在包体中使用,不必再在包体中定义。
(1)、语法:
create or replace package body [schema.] package_name {is/as}
pl/sql_body;
其中package_name为包名,该包名必须与定义包头时的名称一样,pl/sql_body为过程与函数的定义
如果包头不包含存储过程和函数,则不必定义包体。如果包头中有预定义的子程序(存储过程和函数),
则在包体中必须编写其子程序代码,而且包头和包体两部分指定的子程序必须一致。
这包括相同的子程序名、参数名、和参数类型。
例一:
create or replace package body aupack is
procedure qusalary(p_code auths.code%type,p_salary out auths.salary%type) as
begin
...
end aupack;
procedure inauthor(p_code auths.code%type,p_salary out auths.salary%type) as
begin
...
end inauthor;
三、包的初始化
1、概述
包的初始化,也称包的构造过程。类似于C++的构造函数和JAVA的构造方法。
当在会话内第一次被调用时会自动执行,并且在同一会话内只会执行一次。
包的构造过程没有名称,在包体实现了包头定义的子程序后的最后部分被定义,以begin开始、end结束。
2、语法
create or replace package body package_name {is|as}
... --实现包体中过程与函数的定义部分
begin
... --初始化代码
end;
例子
create or replace package apack as
v_sex varchar2(2);
procedure a_sex(p_code auths.code%type,p_sex out varchar2);
end apack;
create or replace body apack as
procedure a_sex(p_code auths.code%type,p_sex out varchar2) as
v_sex number;
begin
select sex into v_sex from auths where code=p_code;
if v_sex=0 then
p_sex:='女';
else
p_sex:='男';
end if;
end apack;
begin
a_sex('A0001',v_sex); --初始化部分
end apack;
四、包中子程序的重载
1、定义
在包的内部,存储过程和函数都可被重载,这意味着有多个存储过程或函数可以使用同一名称,但是参数不能相同。
这样就允许不同的参数调用同一名字的过程或函数。但需要注意同名的函数返回值得数据类型必须完全相同。
例一
create or replace package pac_temp is
procedure ad(p_in number);
procedure ad(p_in varchar2);
end pac_temp;
create or replace package body pac_temp is
procedure ad(p_in number) as
begin
dbms_output.put_line(p_in);
dbms_output.put_line('我是number');
end ad;
procedure ad(p_in varchar2) as
begin
dbms_output.put_line(p_in);
dbms_output.put_line('我是varchar2');
end ad;
end pac_temp;
begin
dbms_output.put_line('a');
pac_temp.ad('5');
pac_temp.ad(5);
end;
2、重载的局限性
(1)、当仅仅参数名不同或者是模式(in,out,in out)不同时,不能重载。
(2)、不能对仅有返回类型不同的函数进行重载。
(3)、重载函数的参数必须是数据类型不同间不可自动转换的。此类错误在编译时不会报错,但调用若自动转换发生错误会报错。
五、包的删除
drop package body pac_name; --只删除包体
drop package pac_name; --删除包
六、包函数的使用纯度级别
1、概述
首先,应该明确这里说的是包里面的函数。要在sql语句中引用包的函数,那么该函数不能含有DML语句,也不能读写远程包的变量。
为了对包的函数加以限制,在定义包头时使用可以使用纯度级别限制函数。
2、语法
pragma restrict_references(function_name,wnds[,wnps,rnds,rnps]); --能在sql语句中调用的函数都有wnds基本约束
四种约束的含义:
WNDS:函数内不能修改数据库数据(即禁止DML操作)。
WNPS:函数内不能修改包变量(即不能给包变量赋值)。
RNDS:函数内不能读取数据数据(即禁止执行select操作)。
RNPS:函数内不能读取包变量(即不能将包变量赋值给其他变量)。
根据对函数的四种基本约束,满足下面约束的函数可以被sql语句调用:
(1)、当函数满足WNDS时,能被SQL语句调用。
(2)、当函数满足RNPS和WNPS约束时,这个函数(通过数据库连接)能被远程或并行调用。
(3)、在select、valules或set子句中调用的函数可以没有wnps约束,但在其它的子句中就必须满足wnps约束。
(4)、一个函数所调用的子程序与该函数的约束级别相同。
(5)、在含有create table或alter table 命令的check子句中,不能调用直接创建的函数,因为这些语句中的定义不能变化。
3、restrict_references编译指令的应用
当将单独存储在数据库中的函数用在sql语句时,plsql引擎自动确定该函数有哪些约束,这些约束能否保证函数在sql语句中的调用。
对于包函数,则先在包内部使用restrict_references编译指令来指定包函数的约束。
在sql语句中调用这个包函数时,plsql根据编译指令指定的约束来来判断包函数能否在sql语句中调用。
例一:
create or replace package authorpack as
function fun(p_authorcode auths.author_code%type) return varchar2;
pragma restrict_references(fun,WNDS,WNPS,RNPS); --指定3种约束
function authorcount return number;
pragma restrict_references(authorcount,WNDS,WNPS,RNPS)
end authorpack;
create or replace body authorpack as
v_num number; --包变量
function fun(p_authorcode auths.author_code%type) return varchar2 as
v_return varchar2(16);
begin
select author||name into v_return from auths where author_code=p_authorcode;
return v_return;
end fun;
function authorcount return number as
v_return number;
begin
if v_num is null then --包变量被读,不满足RNPS
select count(*) into v_return from auths where author_code like 'A%';
v_num:=v_return; --包变量被修改,不满足WNPS
else
v_return:=v_num;
end if;
return v_return;
end authorcount;
end authorpack;
例二
create or replace package purity is
minsal number(6,2);
maxsal number(6,2);
function max_sal return number;
function min_sal return number;
pragma restrict_references(max_sal,WNPS);
pragma restrict_references(min_sal,WNPS);
end;
create or replace package body purity is
function max_sal return number is
begin
select max(sql) into maxsal from emp; --违反WNPS
return maxsal;
end;
function min_sal return number is
begin
select max(sql) into maxsal from emp; --违反WNPS
return maxsal;
end;
end;
在包头的fun函数中使用了restrict_references编译指令指定约束,包体中的fun函数代码显然符合编译指令指定的约束——没有修改数据库表、没有读包中变量、没有修改包中变量。
在包头的authorcount函数中使用了restrict_references编译指令,但在包体中的authorcount函数代码
并不符合指定的约束,包体中定义的变量v_num不仅仅被该函数读出(不满足rnps约束),而且被修改(不满足wnps约束),
所以plsql引擎编译到函数authorcount是,会报“pls-00452”的错误。
注意事项:
(1)、plsql编译程序根据编译指令来确认包函数的基本约束,从而确认这个包函数是否能在sql语句中使用。
只要随后修改了包体(或第一次创建),就要按照编译指令校检函数代码。
(2)、包初始化部分的代码同样也可以有基础约束。包的基本约束也用restrict_references来指定,
但应以包名为参数而不是以函数名为参数。
(3)、restrict_references可在包中函数定义后的任何位置出现,但它只能约束一个函数的定义。
因此,对于函数的重载,pragma只约束最近定义的函数。
(4)、如果函数中用到了系统包,则该函数不能用在sql语句中。常见系统包dbms_output,dbms_pipe,dbms_alter,dbms_sql,utl_file等。
(5)、当过程性语句中调用一个函数时,可以使用参数缺省值,而通过sql语句调用一个函数时,所有的参数都必须指定。
另外必须使用位置表示法,而不能使用名称表示法。
Oracle Package的更多相关文章
- Oracle Package的全局变量与Session
Oracle Package的全局变量与Session2012-07-26 aaie_ 阅 3595 转 10简单讲,同一个session下pageckage中的全局变量时公共的,会导致冲突.以下是一 ...
- C#/java 执行oracle package
使用pl/sql创建package CREATE OR REPLACE PACKAGE FirstPage is type outlist is ref cursor; Procedure p_get ...
- Oracle package demo 包
1.package 程序包说明(由函数.过程.变量.常量.游标和异常组成) create or replace package pk_test is -- Author : CHEN -- Creat ...
- ORACLE PACKAGE中查看包的依赖关系
SELECT dd.* FROM dba_dependencies dd WHERE NAME <> referenced_name AND referenced_type <> ...
- oracle package pragma SERIALLY_REUSABLE(编译指示 告诉PL/SQL 的运行时引擎,在数据引用之时不要保持包级数据。)
当包第一次被动调用时,将进行初始化:比如将包从硬盘上调到内存中来,放到系统全局工作区的共享缓冲池中,包的运行状态则被放到用户全局区的会话中存储区中,因此可以保证每个调用包的会话都拥有包的运行副本,当会 ...
- Oracle中 Package与Package body的介绍
1.Oracle Package的作用: 可以简化应用设计.提高应用性能.实现信息隐藏.子程序重载 2.ORACLE中的function .package.package bodies.pro ...
- csharp: ODP.NET,System.Data.OracleClient(.net 4.0) and System.Data.OleDb读取Oracle g 11.2.0的区别
ODP.NET: 引用: using Oracle.DataAccess; //Oracle g 11.2.0 using Oracle.DataAccess.Client; using Oracle ...
- JDBC链接oracle已经mysql的测试
1.链接oracle package cn.itcast.mybatis.dao; import java.sql.Connection;import java.sql.DriverManager;i ...
- oracle 笔记
1.Oracle认证,与其它数据库比较,安装 Oracle安装会自动的生成sys用户和system用户: (1)sys用户是超级用户,具有最高权限,具有sysdba角色,有create databas ...
随机推荐
- 【我的Android进阶之旅】解决SVN Cleanup错误: Failed to run the WC DB work queue associated with
错误描述 在Android Studio中点击VCS向下箭头使用SVN Update功能更新代码的时候,报错如下所示: 错误描述信息: Error:svn: E155037: Previous ope ...
- 上手Keras
Keras的核心数据是“模型”,模型是一种组织网络层的方式.Keras中主要的模型是Sequential模型,Sequential是一系列网络层按顺序构成的栈. Sequential模型如下: fro ...
- 全球第一张中文网络协议分析图——By 成都科来软件
网上内容比较全面的网络协议图并不是很多,这些网络协议图大多只遵循OSI,对于TCP/IP基本不支持,有些协议图表示也不够准确.另一方面,现在网上能找到的协议图全都是英文版本,使用起来不是很方便.国内的 ...
- node.js---sails项目开发(6)--- 实现分页功能
只需要添加一个文件即可 api/blueprints/find.js 代码如下 /** * Module dependencies */ var util = require('util') ...
- JVM虚拟机—JVM内存
JVM在运行时将数据划分为了5个区域来存储,这5个区域图示如下: 其中方法区和堆对是所有线程共享的内存区域:而java栈.本地方法栈和程序员计数器是运行时线程私有的内存区域. 首先我们熟悉一下一个 J ...
- python2函数
1.函数的定义 函数的定义形式如下: def <name>(arg1,arg2...argN): <statements> 函数的名字必须以字母开头,可以包括下划线.函数的目的 ...
- appium的API
使用的语言是java,appium的版本是1.3.4,java-client的版本是java-client-2.1.0,建议多参考java-client-2.1.0-javadoc. 1.使用Andr ...
- while小用
1.使用while打印1 2 3 4 5 6 8 9 10 #!/usr/bin/env python #encoding: utf-8 num = 1 while num < 11: if ...
- Java并发(4):ThreadLocal
一.对ThreadLocal的理解 ThreadLocal是java.lang包中的一个类,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多.可能很多朋友都知道ThreadLoca ...
- maven 不打包hbm 问题
<build> <resources> <resource> <directory>src/main/java</directory> &l ...