七、包的创建和应用:
包是一组相关过程、函数、变量、常量和游标等PL/SQL程序设计元素的组合,它具有面向对象程序设计语言的特点,是对这些PL/SQL程序设计元素的封装。包类似于C++和Java语言中的类,其中变量相当于类中的成员变量,过程和函数相当于类方法。把相关的模块归类成为包,可使开发人员利用面向对象的方法进行存储过程的开发,从而提高系统性能。
与类相同,包中的程序元素也分为公用元素和私用元素两种,这两种元素的区别是他们允许访问的程序范围不同,即他们的作用域不同。
一个包由两个分开的部分组成:包定义(PACKAGE,包定义部分声明包内数据类型、变量、常量、游标、子程序和异常错误处理等元素,这些元素为包的公有元素。);包主体(PACKAGE BODY,包主体则是包定义部分的具体实现,它定义了包定义部分所声明的游标和子程序,在包主体中海可以声明包的私有元素。)。
例1:
create or replace package demo_pack
is
deptrec dept%rowtype;
function add_dept(dept_no number,dept_name varchar2,location varchar2)
return number;
function remove_dept(dept_no number)
return number;
procedure query_dept(dept_no in number);
end demo_pack;
create or replace package body demo_pack
is
function add_dept(dept_no number,dept_name varchar2,location varchar2)
return number
is
empno_remaining exception;
pragma exception_init(empno_remaining,-1);
/* -1 是违反唯一约束条件的错误代码 */
begin
insert into dept values(dept_no,dept_name,location);
if sql%found then
return 1;
end if;
exception
when empno_remaining then
return 0;
when others then
return -1;
end add_dept;
function remove_dept(dept_no number)
return number
is
begin
delete from dept where deptno = dept_no;
if sql%found then
return 1;
else
return 0;
end if;
exception
when others then
return -1;
end remove_dept;
procedure query_dept(dept_no in number)
is
begin
select * into deptrec from dept where deptno = dept_no;
exception
when no_data_found then
dbms_output.put_line('数据库中没有编码为'||dept_no||'的部门');
when too_many_rows then
dbms_output.put_line('程序运行错误!请使用游标');
when others then
dbms_output.put_line(sqlcode||'---'||sqlerrm);
end query_dept;
begin
null;
end demo_pack;
对包内共有元素的调用:
declare
var number;
begin
var := demo_pack.add_dept(90,'administrator','beijing');
if var = -1 then
dbms_output.put_line(sqlcode||'--'||sqlerrm);
elsif var = 0 then
dbms_output.put_line('该部门记录已经存在!');
else
dbms_output.put_line('添加记录成功!');
demo_pack.quer_dept(90);
dbms_output.put_line(demo_pack.deptrec.deptno||'--'||demo_pack.dep);
var:=demo_dept.remove_dept(90);
if var=-1 then
dbms_output.put_line(sqlcode||'--'||sqlerrm);
elsif var=0 then
dbms_output.put_line('该部门记录不存在!');
else
dbms_output.put_line('删除成功!');
end if;
end if;
end;
例2:
create or replace package emp_package
is
type emp_table_type is table of emp%rowtype index by binary_integer;
procedure read_emp_table(p_emp_table out emp_table_type);
end emp_package;
create or replace package body emp_package
is
porcedure read_emp_table(p_emp_talbe out emp_table_type)
is
l binary_integer:=0;
begin
for emp_record in (select * from emp) loop
p_emp_table(i):=emp_record;
l:=l+1;
end loop;
end read_emp_table;
end emp_package;
declare
e_table emp_package.emp_table_type;
begin
emp_package.read_emp_table(e_table);
for l in e_table.first .. e_table.last loop
dbms_output.put_line(e_table(i).empno||'--'||e_table(i).empname);
end loop;
end;
例3:
create sequence empseq start with 1000 increment by 1 order nocycle;
create sequence deptseq start with 50 increment by 10 order nocycle;
create or replace package emp_mgmt
as
function hire(ename varchar2,job varchar2,mgr number,sal number,comm number, deptno number) return number;
function create_dept(dname varchar2,loc varchar2) return number;
procedure remove_emp(empno number);
procedure remove_dept(deptno number);
procedure increase_sal(empno number,sal_incr number);
procedure increase_comm(empno number,comm_incr number);
end emp_mgmt;
create or replace package body emp_mgmt
as
tot_emps number;
tot_depts number;
no_sal exception;
no_comm exception;
function hire(ename varchar2,job varchar2,mgr number,sal number,comm number, deptno number)
return number is
new_empno number(4);
begin
select empseq.nextval into new_empno from dual;
insert into emp values(new_empno,ename,job,mgr,sysdate,sal,comm,deptno);
tot_emps:=tot_emps+1;
return(new_empno);
exception
when others then
dbms_output.put_lien('发生其他错误');
end hire;
function create_dept(dname varchar2,loc varchar2)
return number is
new_deptno number(4);
begin
select deptseq.nextval into new_deptno from dual;
insert into dept values(new_deptno,dname,loc);
tot_depts:=tot_depts+1;
return(new_deptno);
exception
when others then
dbms_output.put_line("发生其他错误");
end create_dept;
procedure remove_emp(empno number)
is
no_result exception;
begin
delete from emp where emp.empno=remove_emp.empno;
if sql%notfound then
raise no_result;
end if;
tot_emps:=tot_emps-1;
exception
when no_result then
dbms_output.put_line('你需要的数据不存在!');
when others then
dbms_output.put_line('发生其他错误');
end remove_emp;
procedure remove_dept(deptno number)
is
no_result exception;
e_deptno_remaining exception;
pragma exception_init(e_deptno_remaining,-2292);
/* -2292 是违反一致性约束的错误代码 */
begin
delete from dept where dept.deptno=remove_dept.deptno;
if sql%notfound then
raise no_result;
end if;
tot_depts:=tot_depts-1;
exception
when no_result then
dbms_output.put_line('你需要的数据不存在!');
when e_deptno_remaining then
dbms_output.put_line('违反数据完整性约束!');
when others then
dbms_output.put_line('发生其他错误');
end remove_dept;
procedure increase_sal(empno number,sal_incr number)
curr_sal number(7,2);
begin
select sal into curr_sal from emp where emp.empno=increase_sal.empno;
if curr_sal is null then
raise no_sal;
else
update emp set sal=sal+increase_sal.sal_incr where emp.empno=increase_sal.empno;
end if;
exception
when no_data_found then
dbms_output.put_line('你需要的数据不存在');
when no_sal then
dbms_output.put_line('此员工的工资不存在');
when others then
dbms_output.put_line('发生其他错误');
end increase_sal;
procedure increase_comm(empno number,comm_incr number)
curr_comm number(7,2);
begin
select comm into curr_comm from emp where emp.empno=increase_comm.empno;
if curr_comm is null then
raise no_comm;
else
update emp set comm=comm+increase_comm.comm_incr where emp.empno=increase_comm.empno;
end if;
exception
when no_data_found then
dbms_output.put_line('你需要的数据不存在');
when no_comm then
dbms_output.put_line('此员工的奖金不存在');
when others then
dbms_output.put_line('发生其他错误');
end increase_comm;
end emp_mgmt;