PL/SQL–package
Package 组成:
Package 由包规范(package Specification) 和包体(package body) 两部分构成; 包规范部分相当于C 语言里面的.H 文件,包体部分相当于 C 语言里面针对.H 实现的C 文件。
Package 好处
1 、模块化:一般把有相关性的函数和过程放到一个Package 中;
2 、易设计:可以把包说明和包体分别编写和编译,先编写和编译包说明部分,在编写和说明包体部分;这有利于分工合作;
3 、信息隐藏:包体中函数可以部分出现在包说明中,只有出现在包说明中的函数和过程才是该Package 的公有函数和过程,可以被其他包中的函数调用,否则对其他包中的函数是不可见的,未在包说明部分出现的函数和过程相当于私有的。
4 、加载性能提高:当Package 中有一个函数或过程被调用时,整个Packege就 就该 被加载到内存中,这样当该Package 中其他函数被调用时,就直接从内存读取了,可以减少磁盘IO, 从而提高性能。 这个特性也提醒我们不要去搞巨无霸的Package, 把你用到的任何 函数都写到一个Package 中,这会导致严重的内存浪费。
5 、重载:一个package 中可以定义同名、不同参数的函数或过程。
创建包规范
create or replace package emp_pkg is
v_max_lines number := 4;
--获取指定条件的用户信息
--min_salary:最低工资
--dep_id:部门ID
procedure p_get_emp_info(min_salary number, dep_id number);
--获取员工姓名
--emp_id:员工ID
function p_get_emp_name(emp_id number) return varchar2;
end emp_pkg;
创建包体
只有在包规范中声明了,
create or replace package body emp_pkg is
--实现声明的存储过程
procedure p_get_emp_info(min_salary number, dep_id number) is
--声明私有,不需要declare
v_flag number(5) := 1;
v_all_salary number(10) := 0;
v_emp_count number(5) := 0;
type emp_type is record
(v_name varchar2(30),
v_salary varchar(20),
v_dep varchar2(30),
v_date date,
v_manager varchar2(30));
type emp_array_type
is table of emp_type
index by binary_integer;
emp_array emp_array_type;
cursor emp_cursor is
select emp.first_name || '.' || emp.last_name v_name,
emp.salary v_salary,
dep.department_name v_dep,
emp.hire_date v_hiredate,
manager.first_name || '.' || manager.last_name v_manager
from employees emp, departments dep, employees manager
where emp.department_id = dep.department_id
and emp.manager_id = manager.employee_id
and min_salary < emp.salary
and emp.department_id = dep_id
and rownum < v_max_lines;
begin
--v_max_lines := 2;这一句会让结果只返回两条
dbms_output.put_line(rpad('姓名', 20) || rpad('薪资',13) ||rpad('部门',18) ||rpad('入职日期',20) || rpad('管理员', 20));
open emp_cursor;
fetch emp_cursor bulk collect into emp_array;
close emp_cursor;
for i in 1..emp_array.count loop
v_all_salary := v_all_salary + emp_array(i).v_salary;
v_emp_count := v_emp_count + 1;
dbms_output.put_line(rpad(emp_array(i).v_name, 20)
|| rpad(to_char(emp_array(i).v_salary, '99999.99'),13)
|| rpad(emp_array(i).v_dep, 18)
|| rpad(to_char(emp_array(i).v_date, 'YYYY-MM-DD'), 20)
|| rpad(emp_array(i).v_manager, 20));
end loop;
dbms_output.new_line();
dbms_output.put_line('工资总额:'||v_all_salary || ' 员工总数:'||v_emp_count);
end;
--实现函数
function p_get_emp_name(emp_id number)
return varchar2
is
--注意,这里不需要declare
v_name varchar2(20);
begin
select emp.first_name || '.' || emp.last_name
into v_name
from employees emp
where emp.employee_id = emp_id;
return v_name;
end;
end emp_pkg;
测试包
begin
--测试存储过程
--emp_pkg.v_max_lines := 1;这句话可以改变了包中公有变量的值,但只是在当前会话中有效
emp_pkg.p_get_emp_info(min_salary => &min_salary, dep_id => &dep_id);
--测试包方法
dbms_output.put_line(emp_pkg.p_get_emp_name(emp_id => &emp_id));
end;