12-Oracle包的定义与使用

本章内容

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 

本人从事软件项目开发20多年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂

讲师课堂链接:https://edu.csdn.net/lecturer/893

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
游标(Cursor)是一种数据库对象,可以用于对查询结果集进行遍历和操作。使用游标可以在程序中逐行处理查询结果,这在需要逐行处理大量数据时非常有用。 在 Oracle 中,游标可以通过以下步骤定义使用: 1. 定义游标 定义游标需要使用 `DECLARE CURSOR` 语句,语法如下: ``` DECLARE cursor_name [IN | OUT | IN OUT] return_datatype; BEGIN ... END; ``` 其中,`cursor_name` 是游标的名称,`return_datatype` 是游标返回的结果集类型。 2. 打开游标 使用 `OPEN` 语句打开游标,语法如下: ``` OPEN cursor_name; ``` 3. 获取游标数据 使用 `FETCH` 语句获取游标中的数据,语法如下: ``` FETCH cursor_name INTO variable_name1 [, variable_name2 ...]; ``` 其中,`variable_name1`、`variable_name2` 等是变量名,用于存储游标中的数据。 4. 关闭游标 使用 `CLOSE` 语句关闭游标,语法如下: ``` CLOSE cursor_name; ``` 下面是一个示例,演示如何定义、打开、获取和关闭游标: ``` DECLARE CURSOR c_emp IS SELECT employee_id, first_name, last_name FROM employees; v_emp_id NUMBER; v_emp_first_name VARCHAR2(50); v_emp_last_name VARCHAR2(50); BEGIN OPEN c_emp; LOOP FETCH c_emp INTO v_emp_id, v_emp_first_name, v_emp_last_name; EXIT WHEN c_emp%NOTFOUND; DBMS_OUTPUT.PUT_LINE(v_emp_id || ' ' || v_emp_first_name || ' ' || v_emp_last_name); END LOOP; CLOSE c_emp; END; ``` 该示例定义了一个名为 `c_emp` 的游标,返回的结果集含 `employee_id`、`first_name` 和 `last_name` 字段。然后打开游标、获取游标数据并输出,最后关闭游标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CSDN专家-赖老师(软件之家)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值