包的创建分为两部分,包规范和包体。
1、包定义:包定义部分是为应用程序的接口,声明包内数据类型、变量、常量、游标、子程序和异常错误处理等元素,这些元素为包的公有元素。
CREATE [OR REPLACE] PACKAGE package_name
{IS | AS}
[公有数据类型定义]
[公有游标声明]
[公有变量、常量声明]
[公有子程序声明]
END [package_name];
2、包主体:包主体则是包定义部分的具体实现,它定义了包定义部分所声明的游标和子程序,在包主体中还可以声明包的私有元素。如果在包主体中的游标或子程序并没有在包头中定义,那么这个游标或子程序是私有的。
CREATE [OR REPLACE] PACKAGE BODY package_name
{IS | AS}
[私有数据类型定义]
[私有变量、常量声明]
[私有子程序声明和定义]
[公有子程序定义]
BEGIN
执行部分(初始化部分)
END [package_name];
与类相同,包中的程序元素也分为公用元素和私用元素两种,这两种元素的区别是他们允许访问的程序范围不同,即它们的作用域不同。公用元素不仅可以被包中的函数、过程所调用,也可以被包外的PL/SQL程序访问,而私有元素只能被包内的函数和过程序所访问。
包定义和包主体分开编译,并作为两部分分开的对象存放在数据库字典中。包定义一定要在包主体前面编译,包主体可以没有,但包定义一定要有) 包的名称和包体的名称要保持一致。
以下为举例:
如果给现有的包添加新的函数、过程等,直接在脚本中增加即可,然后全部执行。
例如下面的创建基本中,分页的过程是已经存在的,现在要添加一个SplitIn函数,则直接在脚本中添加即可。
create or replace package PAK_001 is
--分页
type t_cursor is ref cursor;
procedure Proc_Pagination(p_tableName varchar2,p_fields varchar2,p_filter varchar2,p_sort varchar2,p_curPage number,p_pageSize number,p_cursor out t_cursor,p_totalRecords out number);
--分隔字符串函数
TYPE str_split IS TABLE OF VARCHAR2 (4000);
FUNCTION SplitIn(p_string IN VARCHAR2, p_delimiter IN VARCHAR2) RETURN str_split PIPELINED;
end PAK_001;
create or replace package body PAK_001 is
--分页
procedure Proc_Pagination(
p_tableName varchar2,--要查询的表名
p_fields varchar2,--要查询的字段
p_filter varchar2,--过滤条件
p_sort varchar2,--排序字段及方向
p_curPage number,
p_pageSize number,
p_cursor out t_cursor,
p_totalRecords out number
)
is
v_sql varchar2(2000):='';
v_startRecord number(4);
v_endRecord number(4);
begin
--获取总的记录数
v_sql:='select to_number(count(*)) from '||p_tableName;
if p_filter is not null then
v_sql:=v_sql||' where 1=1 and '||p_filter;
end if;
execute immediate v_sql into p_totalRecords;
v_startRecord:=(p_curPage-1)*p_pageSize;
v_endRecord:=p_curPage*p_pageSize;
v_sql:='select '||p_fields||' from (select '||p_fields||',rownum r from '||
'(select '||p_fields||' from '||p_tableName;
if p_filter is not null then
v_sql:=v_sql||' where 1=1 and '||p_filter;
end if;
if p_sort is not null then
v_sql:=v_sql||' order by '||p_sort;
end if;
v_sql:=v_sql||') A where rownum<='||to_char(v_endRecord)||') B where r>='||to_char(v_startRecord);
open p_cursor for v_sql;
end Proc_Pagination;
--分隔字符串
FUNCTION SplitIn(p_string IN VARCHAR2, p_delimiter IN VARCHAR2)
RETURN str_split PIPELINED
AS
v_length NUMBER := LENGTH(p_string);
v_start NUMBER := 1;
v_index NUMBER;
BEGIN
WHILE(v_start <= v_length)
LOOP
v_index := INSTR(p_string, p_delimiter, v_start);
IF v_index = 0
THEN
PIPE ROW(SUBSTR(p_string, v_start));
v_start := v_length + 1;
ELSE
PIPE ROW(SUBSTR(p_string, v_start, v_index - v_start));
v_start := v_index + 1;
END IF;
END LOOP;
RETURN;
END SplitIn;
end PAK_001;