1.包相关概念介绍
包就是把相关的存储过程、函数、变量、常量和游标等pl/sql程序组合在一起,并赋予一定的管理功能的程序块。
- 包:由包头 + 包体组成
- 包头相当于是 目录;
- 包体相当于是 内容;
- 包头名和包体名必须一致!
- 创建完包头包体之后,我们就可以将 存储过程&自定义函数 封装到包里面去。
2.创建包和包体的具体步骤
1.将 程序块的 create or replace 去掉,放到 包体里面;
2.将程序块 is 之前的内容 放到 包头,作为一个目录;
3.编译(最好 用pl/sql 美化器,美化一下,然后再编译) ,点击执行按钮
4.调用
包里面存储过程调用:
begin 包名.存储过程名称(入参); end;
包里面自定义函数调用:
select 包名.自定义函数名称(入参) from 表;
3.创建包头的语法结构
create or replace package pk_test1 --- 包名 不区分包头名和包体名,只有一个包名
is
procedure sp_name1; --存储过程:procedure 存储过程名
procedure sp_name2(p_1 in number ....) ; ---可以写多个存储过程
function fun_name1 --自定义函数: function 函数名
return 数据类型; -- 返回一个数据类型 这一句不要忘了
function fun_name2(p_1 in number) ---可以写多个函数
return 数据类型;
end; 4.创建包体的语法结构
create or replace package body pk_test1 --包名
is
procedure sp_name1 --- 跟包头里面定义的 存储过程名 一致
is
begin
......
end ;
procedure sp_name2(p_1 in number ....)
is
begin
......
end ;
function fun_name1
return 数据类型
is
begin
......
end fun_name1;
function fun_name2(p_1 in number)
return 数据类型
is
begin
......
end fun_name2;
end; 5.创建包头和包体练习
5.1练习1
创建包头:
create or replace package pk_0607 --- 包名 is procedure p_10(p_empno number); function p_max_min(m number, n number) return number; end;
创建包体:
create or replace package body pk_0607 --包名
is
procedure p_10(p_empno number) as
v_job varchar2(10); -- 定义变量
cursor c1 is -- 定义游标
select * from emp where job = v_job;
begin
select job into v_job from emp where empno = p_empno;
for i in c1 loop
insert into emp_0317
values
(i.empno,
i.ename,
i.job,
i.mgr,
i.hiredate,
i.sal,
i.comm,
i.deptno);
commit;
end loop;
end;
function p_max_min(m number, n number) return number is
temp number;
begin
if m > n then
temp := m;
else
temp := n;
end if;
return temp;
end;
end;
调用包体中的存储过程:
begin pk_0607.p_10(7788); end; select * from emp_0317;

调用包体中的自定义函数
select pk_0607.p_max_min(3, 1) from dual;

5.2练习2
开发一个包p_test_pkg,里面封装两个存储过程,一个自定义函数
1.存储过程a 有入参 p_empno将 emp表 中 p_empno对应部门的 所有员工同步到 emp_1134;
2.存储过程b,全量同步dept 到dept_1134;
3.自定义函数 实现一个功能,返回 入参 p_empno 的薪资,自定义异常,如果员工不存在,则返回0;
4.创建包 + 验证。
(1)存储过程a 有入参 p_empno将 emp表 中 p_empno对应部门的 所有员工同步到 emp_1134;
建表:
drop table emp_1134; create table emp_1134 as select * from emp where 1=2;
创建存储过程:
create or replace procedure p_a(p_empno number) as
v_source varchar2(20);
v_target varchar2(20);
v_st date;
v_dt date;
v_ct number := 0;
v_job varchar2(10); -- 定义变量
cursor c1 is -- 定义游标
select * from emp where job = v_job;
begin
v_st := sysdate;
v_source := 'emp';
v_target := 'emp_1134';
select job into v_job from emp where empno = p_empno;
for i in c1 loop
insert into emp_1134
values
(i.empno, i.ename, i.job, i.mgr, i.hiredate, i.sal, i.comm, i.deptno);
commit;
v_ct := v_ct + 1; -- 每次插入后递增计数器
end loop;
v_dt := sysdate;
-- 调用日志表存储过程
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => v_ct,
p_status => '成功',
p_start_dt => v_st,
p_end_dt => v_dt,
p_mark => '');
-- 定义异常
exception
when others then
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => 0,
p_status => '失败',
p_start_dt => v_st,
p_end_dt => null,
p_mark => sqlerrm);
end;调用存储过程:
begin p_a(p_empno=>7788); end; select * from emp_1134;

select * from log_table;

(2)存储过程b,全量同步dept 到dept_1134;
建表:
drop table dept_1134; create table dept_1134 as select * from dept where 1=2;
创建存储过程:
create or replace procedure p_b as
v_source varchar2(20);
v_target varchar2(20);
v_st date;
v_dt date;
v_ct number := 0;
begin
v_st := sysdate;
v_source := 'dept';
v_target := 'dept_1134';
insert into dept_1134
select * from dept;
v_ct := sql%rowcount;
commit;
v_dt := sysdate;
-- 调用日志表存储过程
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => v_ct,
p_status => '成功',
p_start_dt => v_st,
p_end_dt => v_dt,
p_mark => '');
-- 定义异常
exception
when others then
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => 0,
p_status => '失败',
p_start_dt => v_st,
p_end_dt => null,
p_mark => sqlerrm);
end;
调用存储过程:
begin p_b; end; select * from dept_1134;

select * from log_table;

(3)自定义函数 实现一个功能,返回 入参 p_empno 的薪资,自定义异常,如果员工不存在,则返回0;
create or replace function f_sal(p_empno number) return number as
v_sal number;
emp_not_found exception;
begin
begin
select sal into v_sal from emp where empno = p_empno; -- 执行查询
exception
when no_data_found then
raise emp_not_found; -- 关键:手动触发自定义异常
end;
return v_sal;
exception
when emp_not_found then
-- 现在能捕获到自定义异常
return 0;
end;
select f_sal(7788),f_sal(778) from dual;
创建包头:
create or replace package p_test_pkg is procedure p_a(p_empno number); -- 1. procedure p_b; function f_sal(p_empno number) return number; end;
创建包体:
create or replace package body p_test_pkg --包名
is
------------ procedure p_a
procedure p_a(p_empno number) as
v_source varchar2(20);
v_target varchar2(20);
v_st date;
v_dt date;
v_ct number := 0;
v_job varchar2(10); -- 定义变量
cursor c1 is -- 定义游标
select * from emp where job = v_job;
begin
v_st := sysdate;
v_source := 'emp';
v_target := 'emp_1134';
select job into v_job from emp where empno = p_empno;
for i in c1 loop
insert into emp_1134
values
(i.empno,
i.ename,
i.job,
i.mgr,
i.hiredate,
i.sal,
i.comm,
i.deptno);
commit;
v_ct := v_ct + 1; -- 每次插入后递增计数器
end loop;
v_dt := sysdate;
-- 调用日志表存储过程
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => v_ct,
p_status => '成功',
p_start_dt => v_st,
p_end_dt => v_dt,
p_mark => '');
-- 定义异常
exception
when others then
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => 0,
p_status => '失败',
p_start_dt => v_st,
p_end_dt => null,
p_mark => sqlerrm);
end;
------------ procedure p_b
procedure p_b as
v_source varchar2(20);
v_target varchar2(20);
v_st date;
v_dt date;
v_ct number := 0;
begin
v_st := sysdate;
v_source := 'dept';
v_target := 'dept_1134';
insert into dept_1134
select * from dept;
v_ct := sql%rowcount;
commit;
v_dt := sysdate;
-- 调用日志表存储过程
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => v_ct,
p_status => '成功',
p_start_dt => v_st,
p_end_dt => v_dt,
p_mark => '');
-- 定义异常
exception
when others then
p_log(p_source_table_name => v_source,
p_target_table_name => v_target,
p_step_name => v_source || ' to ' || v_target,
p_row_count => 0,
p_status => '失败',
p_start_dt => v_st,
p_end_dt => null,
p_mark => sqlerrm);
end;
------------ function f_sal(p_empno number)
function f_sal(p_empno number) return number as
v_sal number;
emp_not_found exception;
begin
begin
select sal into v_sal from emp where empno = p_empno; -- 执行查询
exception
when no_data_found then
raise emp_not_found; -- 关键:手动触发自定义异常
end;
return v_sal;
exception
when emp_not_found then
-- 现在能捕获到自定义异常
return 0;
end;
end;
清空相关表:
truncate table dept_1134; truncate table emp_1134; truncate table log_table;
调用第一个存储过程:
begin p_test_pkg.p_a(7788); end; select * from emp_1134;

调用第二个存储过程:
begin p_test_pkg.p_b; end; select * from dept_1134;

查询日志表:
select * from log_table;

调用自定函数:
select p_test_pkg.f_sal(7369),p_test_pkg.f_sal(778) from dual;

6.存储过程和自定义函数区别
1.函数必须要有返回值,函数里面不能调用存储过程
2.存储过程里面可以调用自定义函数,可以调用存储过程,存储过程不需要返回值
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论