您现在的位置是:首页 > 正文

12-Oracle包的定义与使用

2024-01-30 21:30:10阅读 0

本章内容

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

网站文章

  • 面试篇--网络通信

    面试篇--网络通信

    目录【前言】【TCP三次握手】在TCP/IP协议中,TCP协议提供可靠的连接服务,采用 三次握手建立一个连接.1.第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEN...

    2024-01-30 21:30:03
  • 阿里面试题

    阿里面试题

    阿里面试题文章目录阿里面试题JDK、JRE、JVM之间的区别hashCode()与equals()之间的关系String、StringBuffer、StringBuilder的区别泛型中extends...

    2024-01-30 21:29:48
  • leecode 450. 删除二叉搜索树中的节点

    leecode 450. 删除二叉搜索树中的节点

    450. 删除二叉搜索树中的节点 本题是删除搜索树中的指定值,和添加值比,却复杂很多,但是本题的具体逻辑我竟然能自己慢慢实现出来,第一次感觉到对递归理解加深了。/** * Definition ...

    2024-01-30 21:29:17
  • 图片的黑魔法——GitHub 热点速览 v.21.13

    图片的黑魔法——GitHub 热点速览 v.21.13

    作者:HelloGitHub-小鱼干图片的黑魔法并不是图片修复、旧照上色,而是将任意文件打包成图片的样子,上传到推特。看过去这张图片平平无奇,那么普通却深藏不露,工程师 DavidBuch...

    2024-01-30 21:29:09
  • JS数组对象——英文按照首字母进行排序sort()、localeCompare()

    JS数组对象——英文按照首字母进行排序sort()、localeCompare()

    排序在后台管理系统对于数据的处理中用得非常多。本期文章重点介绍根据英文首字母排序。将用到JavaScript的sort()和localeCompare()方法。

    2024-01-30 21:29:01
  • a-descriptions-item描述列表点击按钮显示相应内容

    a-descriptions-item描述列表点击按钮显示相应内容

    实现功能:点击查询按钮,显示相应数据,部分数据只读,部分数据可修改。 实现思路:首先通过点击按钮事件从接口获取内容,然后通过{{}}显示在界面上。 查询按钮触发事件代码 searchQuery(){ ...

    2024-01-30 21:28:30
  • exe4j使用方法

    exe4j使用方法

    1.选jar in exe。2.选择jar包,选择主类。

    2024-01-30 21:28:24
  • Android ADIL和BInder

    Android ADIL和BInder

    AIDL(Android接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口。在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进都分隔开...

    2024-01-30 21:28:16
  • 版本管理-SVN冲突爆红后如何通过颜色和快捷键准确无误地合并代码(一)

    版本管理-SVN冲突爆红后如何通过颜色和快捷键准确无误地合并代码(一)

    SVN冲突出现场景如今是一个团结协作的时代,开发一个系统,往往会多人协作共同完成。版本管理是必不可少的,常用的软件有Git,SVN等。今天说一下,SVN管理版本时,如果出现冲突后,如何快速解决冲突。首...

    2024-01-30 21:27:47
  • pom.xml配置文件讲解

    Maven 构件工程的属性文件 pom.xml文件(实践用):    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    2024-01-30 21:27:39