Package是plsql语言中的一种对象。
和存储过程一样都是对象,之所以放在存储过程来说它,就是除了语法,基本上
没什么可说的。类比java,包package就是接口与实现类的关系。包package的出现
主要也是为了面向接口编程(个人理解)。你可以把java接口的知识类比学习包package。
里面可以放一些变量定义,方法定义,存储过程定义。
包package分为两大部分:包说明和包体。
包说明类似接口定义,包体类似实现类。
包说明的格式:
create or replace package ppppppppppppp is
-- Author : MY
-- Created : 2013/7/11 16:19:16
-- Purpose :
-- Public type declarations
type <TypeName> is <Datatype>;
-- Public constant declarations
<ConstantName> constant <Datatype> := <Value>;
-- Public variable declarations
<VariableName> <Datatype>;
-- Public function and procedure declarations
function <FunctionName>(<Parameter> <Datatype>) return <Datatype>;
end ppppppppppppp;
包体的声明格式:
create or replace package body bbbbbbbbbbbbb is
-- Private type declarations
type <TypeName> is <Datatype>;
-- Private constant declarations
<ConstantName> constant <Datatype> := <Value>;
-- Private variable declarations
<VariableName> <Datatype>;
-- Function and procedure implementations
function <FunctionName>(<Parameter> <Datatype>) return <Datatype> is
<LocalVariable> <Datatype>;
begin
<Statement>;
return(<Result>);
end;
begin
-- Initialization
<Statement>;
end bbbbbbbbbbbbb;
包说明和包体是1-0或1-1的关系。
如果只是声明变量,不涉及到方法和存储过程,那么只有包说明就可以正确编译和使用。
如果在包说明中除了定义变量还定义了其他的对象,像方法,存储过程。那就必须有包体,并在包体中实现定义的方法和存储过程。(这点和接口实现类很像,就是单继承和java接口不一样)。如果不实现,编译不报错,调用会报错。
包中对象的调用都是通过包名.变量名来调用。
到现在为止,包的好处和意义也应该清楚了。
首先,包的意义就是为了共享。这是一个编程很重要的问题。在java中,我们写一个类,
目的是为了调用。在其他地方,你可以直接new出来,就可以重复使用里面的方法,或者
这个类就是一种数据类型。这很容易理解。但是在plsql中我们声明一种自定义数据类型
(type),如果只在代码块的声明处定义,那就不能让其他对象共享。带来的问题就是如果返回结果是这种类型,怎么让其他对象认识?
有了包,就使得plsql更像编程而不是简单的sql语句组合。
其次,包的结构类似java中的接口。这种设计的好处你可以认为就是面向接口编程的好处。
(注意,包体中实现包说明中的定义时,必须和声明一模一样!包括变量的名字!)
包说明:
create or replace package lsy_package is
--类型
type type_myrecord1 is record(
r_codecode lsy_codebook.codecode%type not null := 'i am default value',
r_codename lsy_codebook.codename%type,
r_result varchar2(32) default null,
r_flag number default 0);
--constant变量声明(必须赋值,类似java中final)
date_pattern_str constant varchar2(32) := 'yyyy-mm-dd hh24:mi:ss';
--变量声明
v_pub_yes varchar2(32) := 'yes';
myexception_package_one exception; --异常
procedure procc(ppp in number); --存储过程
function funcff(fff in number) return number; --方法
end lsy_package;
包体:
create or replace package body lsy_package is
-- 私有的类型type声明
type body_type is record(
r_one varchar2(32) not null := '',
r_two number);
-- 私有的constant变量声明
pub_body_true constant varchar2(32) := '1';
pub_body_false constant varchar2(32) := '0';
-- 私有的变量声明
v_now date := sysdate;
v_now_str varchar2(32);
-- 实现继承的方法和存储过程(也可以有私有的,那样只能在包体中使用,不能被调用)
procedure procc(ppp in number) is
rr number;
begin
rr := ppp + 1;
dbms_output.put_line('procc被调用:' || rr);
exception
when myexception_package_one then
raise_application_error(-20000,
'lsy_package中自定义异常:xxx!',
false);
when others then
raise;
end procc;
--
function funcff(fff in number) return number is
res number;
begin
res := fff + 1;
dbms_output.put_line('funcff被调用:' || res);
return res;
end;
begin
--在第一次调用时这个代码块只走一次
v_now_str := to_char(v_now, date_pattern_str);
dbms_output.put_line('初始化时间:' || v_now_str);
end lsy_package;
匿名代码块测试;
-- Created on 2013/7/11 by lsy
-- package测试1
declare
v_one lsy_package.type_myrecord1;
begin
v_one.r_codecode := 'qq';
v_one.r_codename :='ww';
v_one.r_result:='success!';
v_one.r_flag:=1;
dbms_output.put_line('v_one.r_codecode:' ||
v_one.r_codecode ||
',v_one.r_codename:' ||
v_one.r_codename||
',v_one.r_result:'||v_one.r_result||
',v_one.r_flag:'||v_one.r_flag);
dbms_output.put_line('lsy_package.date_pattern_str:' ||lsy_package.date_pattern_str );
dbms_output.put_line('lsy_package.v_pub_yes:' ||lsy_package.v_pub_yes );
dbms_output.put_line('lsy_package.funcff(3):' ||lsy_package.funcff(3) );
lsy_package.procc(1);
end;
/*打印
v_one.r_codecode:qq,v_one.r_codename:ww,v_one.r_result:success!,v_one.r_flag:1
lsy_package.date_pattern_str:yyyy-mm-dd hh24:mi:ss
lsy_package.v_pub_yes:yes
funcff被调用:4
lsy_package.funcff(3):4
procc被调用:2
*/