1.包用于逻辑组合相关的PL/SQL类型、项和子程序,它由包规范(Package Specification)和包体(Package Body)两部分组成(先建立包规范,在建立包体),包体名称和包规范名称必须相同。
2.包规范相当于接口,建立包规范时(create package),为了实现信息隐藏,不应该就所有组件全部放在包规范处定义,而应该定义公用组件。
例如:
create or replace package emp_package is
g_deptno number(3):=30;
procedure add_employee(eno number,sname varchar2,salary number,dno number default g_deptno);
procedure fire_employee(eno number);
function get_sal(eno number) return number;
end emp_package;
3
.包体相当于实现包规范里面定义的过程和函数,建立包体时(create package body),可以在包体内单独定义私有组件(变量、常量、过程、函数等),在包体内定义的私有组件只能在包内使用,不能由其他子程序调用。
例如:
create or replace package body
emp_package is
function validate_deptno
(v_dept no number)
return boolean
is
v_temp int;
begin
select 1 into v_temp
from scott.dept
where deptno=v_deptno;
return true;
exception
when no_data_found then
return false;
end;
procedure add_employee
(eno number,sname varchar2,
salary number,
dno number default g_deptno)
is
begin
if validate_deptno(dno) then
insert into scott.emp
(empno,ename,sal,deptno)
values(eno,sname,salary,dno);
else
raise_application_error(-20010,'不存在该部门');
end if;
exception
when dup_val_on_index then
raise_application_error(-20011,'该雇员已存在');
end;
procedure fire_employee(eno number) is
begin
delete from scott.emp
where empno=eno;
if sql%notfound then
raise_application_error(-20012,'该雇员不存在');
end if;
end;
function get_sal(eno number)
return number
is
v_sal scott.emp.sal%type;
begin
select sal into v_sal from scott.emp where empno=eno;
return v_sal;
exception
when no_data_found then
raise_application_error(-20012,'该雇员不存在');
end;
end emp_package;
4.包的内部(其包括包规程和包Body里面,除过程里面)可以定义游标类型,但不可以定义游标变量。
5.公用变量不能重复定义,私有变量可以再过程里面定义。
6.包的重载,指多个具有相同名称的子程序。可以使用户在调用同名组件时使用不同参数传递数据。例如:
create or replace package overload is
function get_sal(eno scott.emp.empno%type) return number;
function get_sal(sname scott.emp.ename%type) return number;
procedure fire_employee(eno scott.emp.empno%type);
procedure fire_employee(sname scott.emp.ename%type);
end overload;
--overload 包体
create or replace package body overload is
function get_sal(eno scott.emp.empno%type) return number
is
v_sal scott.emp.sal%type;
begin
select sal into v_sal from scott.emp where empno=eno;
return v_sal;
exception
when no_Data_found then
raise_application_error(-20000,'该雇员不存在');
end;
function get_sal(sname scott.emp.ename%type) return number
is
v_sal scott.emp.sal%type;
begin
select sal into v_sal from scott.emp where upper(ename)=upper(sname);
return v_sal;
exception
when no_Data_found then
raise_application_error(-20000,'该雇员不存在');
end;
procedure fire_employee(eno scott.emp.empno%type) is
begin
delete from scott.emp where empno=eno;
if sql%notfound then
raise_application_error(-20001,'该雇员不存在');
end if;
end;
procedure fire_employee(sname scott.emp.ename%type) is
begin
delete from scott.emp where upper(ename)=upper(sname);
if sql%notfound then
raise_application_error(-20001,'该雇员不存在');
end if;
end;
end overload;
--overload 调用
declare
begin
dbms_output.put_line(overload.get_sal('SCOTT'));
dbms_output.put_line(overload.get_sal(7369));
dbms_output.put_line(get_sal('SCOTT'));
overload.fire_employee('aa');
end;
注:函数和过程名字不能相同,且函数的返回类型必须相同,其他和JAVA中的重载一样。声明时过程和里面的参数同时声明,参数作为过程名的一部分,包的权限赋予(grant exec package_name to user_name)。
7.包的构造过程没有任何名称,它位于程序的尾部,以begin开始,end结束。