在本章中,我们将讨论pl/sql中的包。 包是模式对象,将逻辑上相关的pl/sql类型,变量和子程序分组。
一个包将有两个强制性的部分 -
规范是包的接口。它只是声明可以从包外部引用的类型,变量,常量,异常,游标和子程序。 换句话说,它包含有关包的内容的所有信息,但不包括子程序的代码。
所有放置在规范中的对象被称为公共对象。任何不在包规范中但在包体中编码的子程序称为私有对象。
以下代码片段显示了包含单个过程的包规范。可以在一个包中定义许多全局变量和多个过程或函数。
set serveroutput on size 99999;
create package cust_sal as
procedure find_sal(c_id customers.id%type);
end cust_sal;
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
包体具有包规范中声明的各种方法代码和其他私有声明,这些声明对包之外的代码是隐藏的。
create package body
语句用于创建包体。以下代码片段显示了上面创建cust_sal
包的包体声明。假定已经在数据库中创建了customers
表,有关customers
表的结构和数据,可参考以下sql语句 -
create table customers(
id int not null,
name varchar (20) not null,
age int not null,
address char (25),
salary decimal (18, 2),
primary key (id)
);
-- 数据
insert into customers (id,name,age,address,salary)
values (1, 'ramesh', 32, 'ahmedabad', 2000.00 );
insert into customers (id,name,age,address,salary)
values (2, 'khilan', 25, 'delhi', 1500.00 );
insert into customers (id,name,age,address,salary)
values (3, 'kaushik', 23, 'kota', 2000.00 );
insert into customers (id,name,age,address,salary)
values (4, 'chaitali', 25, 'mumbai', 6500.00 );
insert into customers (id,name,age,address,salary)
values (5, 'hardik', 27, 'bhopal', 8500.00 );
insert into customers (id,name,age,address,salary)
values (6, 'komal', 22, 'mp', 4500.00 );
基于上述customers
表,创建一个简单的包体 -
set serveroutput on size 99999;
create or replace package body cust_sal as
procedure find_sal(c_id customers.id%type) is
c_sal customers.salary%type;
begin
select salary into c_sal
from customers
where id = c_id;
dbms_output.put_line('salary: '|| c_sal);
end find_sal;
end cust_sal;
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
包元素(变量,过程或函数)是用下面的语法来访问的 -
package_name.element_name;
考虑一下,假设已经在数据库模式中创建了上面的包,下面的程序中需要调用cust_sal
包趾的find_sal
方法 -
set serveroutput on size 9999;
declare
code customers.id%type := &cc_id;
begin
cust_sal.find_sal(code);
end;
/
当上述代码在sql提示符下执行时,它会提示输入客户id,当输入一个id时,显示相应的工资如下 -
示例
以下程序提供了一个更完整的包体。使用存储在数据库中的customers
表和以下记录 -
select * from customers;
+----+----------+-----+-----------+----------+
| id | name | age | address | salary |
+----+----------+-----+-----------+----------+
| 1 | ramesh | 32 | ahmedabad | 3000.00 |
| 2 | khilan | 25 | delhi | 3000.00 |
| 3 | kaushik | 23 | kota | 3000.00 |
| 4 | chaitali | 25 | mumbai | 7500.00 |
| 5 | hardik | 27 | bhopal | 9500.00 |
| 6 | komal | 22 | mp | 5500.00 |
+----+----------+-----+-----------+----------+
包规范
set serveroutput on size 99999;
create or replace package c_package as
-- adds a customer
procedure addcustomer(c_id customers.id%type,
c_name customers.name%type,
c_age customers.age%type,
c_addr customers.address%type,
c_sal customers.salary%type);
-- removes a customer
procedure delcustomer(c_id customers.id%type);
--lists all customers
procedure listcustomer;
end c_package;
/
当上面的代码在sql提示符下执行时,它会创建上面的包并显示以下结果 -
创建程序包体
create or replace package body c_package as
procedure addcustomer(c_id customers.id%type,
c_name customers.name%type,
c_age customers.age%type,
c_addr customers.address%type,
c_sal customers.salary%type)
is
begin
insert into customers (id,name,age,address,salary)
values(c_id, c_name, c_age, c_addr, c_sal);
end addcustomer;
procedure delcustomer(c_id customers.id%type) is
begin
delete from customers
where id = c_id;
end delcustomer;
procedure listcustomer is
cursor c_customers is
select name from customers;
type c_list is table of customers.name%type;
name_list c_list := c_list();
counter integer :=0;
begin
for n in c_customers loop
counter := counter +1;
name_list.extend;
name_list(counter) := n.name;
dbms_output.put_line('customer(' ||counter|| ')'||name_list(counter));
end loop;
end listcustomer;
end c_package;
/
上面的例子使用了嵌套表,我们将在下一章讨论嵌套表的概念。
当上面的代码在sql提示符下执行时,它会产生以下结果 -
程序包体已创建。
使用程序包
以下程序使用程序包:c_package 中声明和定义的方法。
set serveroutput on size 99999;
declare
code customers.id%type:= 8;
begin
c_package.addcustomer(7, 'andy liu', 25, 'chennai', 3500);
c_package.addcustomer(8, 'kobe bryant', 32, 'delhi', 7500);
c_package.listcustomer;
c_package.delcustomer(code);
c_package.listcustomer;
end;
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
old salary:
new salary: 3500
salary difference:
old salary:
new salary: 7500
salary difference:
customer(1)ramesh
customer(2)khilan
customer(3)kaushik
customer(4)chaitali
customer(5)hardik
customer(6)komal
customer(7)andy liu
customer(8)kobe bryant
customer(1)ramesh
customer(2)khilan
customer(3)kaushik
customer(4)chaitali
customer(5)hardik
customer(6)komal
customer(7)andy liu
pl/sql 过程已成功完成。