当前位置: 代码网 > it编程>数据库>Oracle > Oracle包是什么?一文带你搞懂包的创建与使用

Oracle包是什么?一文带你搞懂包的创建与使用

2026年09月09日 Oracle 我要评论
本章内容1.包概述2.包的创建3.包的调用4.包重载5.包的初始化6.包的持续性 7.包的串行化 8.包的管理包概述1、包是包含一个或多个子程序单元(过程、函数等)的容器。2、包是一种全局结构 。3、

本章内容

  • 1.包概述
  • 2.包的创建
  • 3.包的调用
  • 4.包重载
  • 5.包的初始化
  • 6.包的持续性
  • 7.包的串行化
  • 8.包的管理

包概述

1、包是包含一个或多个子程序单元(过程、函数等)的容器。

2、包是一种全局结构 。

3、包类型

  • 数据库内置包
  • 用户创建的包

4、包构成

  • 包规范
  • 包体两

1.包规范声明了软件包中所有内容,如过程、函数、游标、类型、异常和变量等,其中过程和函数只包括原型信息,不包含任何子程序代码。

2.包体中包含了在包头中的过程和函数的实现代码。包体中还可以包括在规范中没有声明的变量、游标、类型、异常、过程和函数,但是它们是私有元素,只能由同一包体中其他过程和函数使用。

包的创建

  • 创建包规范
  • 创建包体

(1)创建包规范

  • 语法
create or replace package package_name 
is|as
[pragma serially_resuable]
  type_definition|variable_declaration|
  exception_declaration|cursor_declaration| 
  procedure_ declaration|function_ declaration
end [package_name];

注意:

元素声明的顺序可以是任意的,但必须先声明后使用;

所有元素是可选的;

  • 过程和函数的声明只包括原型,不包括具体实现。
  • 创建一个软件包,包括2个变量、2个过程和1个异常。

(2)创建包体

  • 语法
create or replace package body package_name 
is|as
[pragma serially_resuable]
  type_definition|variable_declaration|
  exception_declaration|
  cursor_declaration| 
  procedure_definition |
  function_definition
end [package_name]; 

注意:

包体中函数和过程的原型必须与包规范中的声明完全一致;

只有在包规范已经创建的条件下,才可以创建包体;

如果包规范中不包含任何函数或过程,则可以不创建包体。

create or replace package body pkg_emp
as
    procedure update_sal(p_empno number, p_sal number)
    as
    begin
      select min(sal), max(sal) into minsal,maxsal from emp;
      if p_sal between minsal and maxsal then
        update emp set sal=p_sal where empno=p_empno;
        if sql%notfound then
          raise_application_error(-20000,'the employee doesn''t exist');
        end if;
      else
        raise e_beyondbound;
      end if;
   exception
      when e_beyondbound then
         dbms_output.put_line('the salary is beyond bound! ');
    end update_sal; 

procedure add_employee(p_empno number,p_sal number)
as
 begin
      select min(sal), max(sal) into minsal,maxsal from emp;
      if p_sal between minsal and maxsal then
         insert into emp(empno,sal) values(p_empno,p_sal);
      else
         raise e_beyondbound;
      end if;
  exception
    when e_beyondbound then
      dbms_output.put_line('the salary is beyond bound! ');
  end add_employee;
end pkg_emp;



包的调用

在包规范声明的任何元素是公有的,在包外都是可见的

包外:通过 package.element 形式调用;

包内:直接通过元素名进行调用。

  • 在包体中定义而没有在包头中声明的元素是私有的,只能在包体中引用
  • 调用软件包 pkg_emp 中的过程 update_sal ,修改 7844 员工工资为 3000 。调用 add_employee 添加一个员工号为 1357 ,工资为 4000 的员工。
begin
   pkg_emp.update_sal(7844,3000);
 pkg_emp.add_employee(1357,4000);
 end;

包重载

重载子程序必须同名不同参,即名称相同,参数不同。参数不同体现为参数的个数、顺序、类型等不同。

如果两个子程序参数只是名称和模式不同,则不能重载。

procedure overloadme (parameter1 in number);
procedure overloadme (parameter2 out number);

不能根据两个函数返回类型不同而对它们进行重载。

function overloadme return date;
function overloadme return number;

重载子程序参数必须在类型系列方面有所不同。

procedure overloadchar (parameter in char);
procedure overloadchar (parameter in varchar2);

在一个包中重载两个过程,分别以部门号和部门名称为参数,查询相应部门员工名、员工号信息。

create or replace package pkg_overload
as
  procedure show_emp(p_deptno number);  
  procedure show_emp(p_dname varchar2);
end pkg_overload;
create or replace package body pkg_overload
as
  procedure show_emp(p_deptno number)
  as
  begin
    for v_emp in (select * from emp where deptno=p_deptno) loop
      dbms_output.put_line(v_emp.empno||'  '|| v_emp.ename);
    end loop;
  end show_emp;

  procedure show_emp(p_dname varchar2)
  as
    v_deptno number;
  begin
    select deptno into v_deptno from dept 
    where dname=p_dname;
    for v_emp in (select * from emp 
                            where deptno=v_deptno) loop
          dbms_output.put_line(v_emp.empno||' '||
                                                 v_emp.ename);
    end loop;
  end show_emp;
end pkg_overload; 

包的初始化

包在第一次被调用时从磁盘读取到共享池,并在整个会话的持续期间保持。在此过程中,可以自动执行一个初始化过程,对软件包进行实例化。

包的初始化过程只在包第一次被调用时执行,因此也称为一次性过程,它是一个匿名的 pl/sql 块,在包体结构的最后,以 begin 开始。

示例

pkg_emp 包中,在包初始化时给 minsal maxsal 两个变量赋值,在子程序中直接引用这两个变量。

create or replace package pkg_emp
as
  minsal   number;
  maxsal   number;
  e_beyondbound  exception;
  procedure update_sal(
    p_empno number, p_sal number);
  procedure add_employee(
    p_empno number,p_sal number);
end pkg_emp; 
create or replace package body pkg_emp
as
  procedure update_sal(p_empno number, p_sal number)
  as
  begin
    if p_sal between minsal and maxsal then
      update emp set sal=p_sal where empno=p_empno;
      if sql%notfound then
         raise_application_error(-20000,'the employee 
                                                     doesn''t exist');
      end if;
    else
      raise e_beyondbound;
    end if;
  exception
    when e_beyondbound then
      dbms_output.put_line('the salary is beyond bound!');
  end update_sal; 

procedure add_employee(p_empno number,p_sal number)
  as
  begin
      if p_sal between minsal and maxsal then
       insert into emp(empno,sal) values(p_empno,p_sal);
    else
        raise e_beyondbound;
    end if;
  exception
    when e_beyondbound then
      dbms_output.put_line('the salary is beyond bound!');
  end add_employee;
begin
    select min(sal), max(sal) into minsal,maxsal from emp;
end pkg_emp;

包的持续性

  • 变量持续性
  • 游标持续性

(1)变量持续性

包中变量的持续性是指,当用户调用包时,会创建自己的变量副本,在用户的整个会话过程中持续存在,对用户而言是私有的。

为了测试变量的持续性,先创建一个包含一个变量的包和对包中变量进行读、写的两个过程。

create or replace package variable_pkg
is
  pkg_test number(6,2) :=0;
end variable_pkg;

create or replace procedure get_pkg_test
 (p_test out number)
is
begin
  p_test := variable_pkg.pkg_test;  
end;
 
create or replace procedure set_pkg_test
 (p_test in number)
is
begin
  variable_pkg.pkg_test := p_test;
end; 

以不同的用户(scottsystem)分别启动两个sql*plus,进行下列操作,可以看出,包中的变量variable_pkg.pkg_testscott用户和system用户之间是持续的、独立的。

--user scott
sql>variable g_test number;
sql>execute  get_pkg_test(:g_test);
sql>print g_test
g_test
----------
  0
sql>execute set_pkg_test(10);
sql>execute get_pkg_test(:g_test);
sql>print g_test
g_test
----------
 10 
--user system
sql>variable g_test number
sql>execute scott.get_pkg_test(:g_test);
sql>print g_test
g_test
----------
  0
sql>execute scott.set_pkg_test(20);
sql>execute scott.get_pkg_test(:g_test);
sql>print g_test
g_test
----------
  20 
--user scott
sql>execute get_pkg_test(:g_test);
sql>print g_test
g_test
----------
 10 

总结

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

(0)

相关文章:

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

发表评论

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