当前位置: 代码网 > it编程>数据库>Oracle > Oracle包是什么?包和包体创建步骤详解

Oracle包是什么?包和包体创建步骤详解

2026年09月08日 Oracle 我要评论
1.包相关概念介绍包就是把相关的存储过程、函数、变量、常量和游标等pl/sql程序组合在一起,并赋予一定的管理功能的程序块。包:由包头+ 包体组成包头相当于是 目录;包体相当于是 内容;包头名和包体名

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.存储过程里面可以调用自定义函数,可以调用存储过程,存储过程不需要返回值

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com