zoukankan      html  css  js  c++  java
  • PL/SQL Package

    Allow the Oralcel server to read multiple objects into memory at once.

    Package bundle related PL/SQL types, items, and subprograms into one container.

    包含2部分 : specification , body ( stored separately in the database )

    The specification is the interface to your applications. ( 声明 )

    body : 真实定义

    The package itself cannot be called . package once written and compiled, the contents can be shared by many applications.

    When you call a packaged PL/SQL construct for the first time, the whole package is loaded into memory. ( thus, later calls to constructs in the same package require no disk input/output I/O )

    Public package : are those that are declared in the package specification and defined in the package body.

    Private package : are those that are defined solely within the package body.

    image

    变量可见度

    image

    G_VARIABLE_NAME ( g 前缀开头的是 Global )

    A package specification can exist without a package body, but a package body cannot exist without a package specification.

    声明: ( specification )

    CREATE [ OR REPLACE ] PACKAGE package_name

    IS | AS

      public type and item declarations

      subprogram specifications

    END package_name;

    例子 :

    image

    包体 ( body )

    CREATE [ OR REPLACE ] PACKAGE BODY package_name

    IS | AS

      private type and item declarations

      subprogram bodies

    END package_name ;

    It is quite common in the package body to see all private variables and subprograms defined first and the public subprograms defined last ( 先定义似有的, 再定义公共变量 )

    例子 :

    image

    调用 :

    EXECUTE comm_package.reset_comm( 0.15 )

    EXECUTE scott.comm_package.reset_comm( 0.15 )   // different schema

    EXECUTE comm_package.reset_comm@ny( 0.15 )     // remote database

    可以只有 specification , 没有 body.

    删除 :

    DROP PACKAGE package_name ;

    DROP PACKAGE BODY package_name;

    包里的东西可以重载,比如 you can careate multiple subprograms with the same name in the same package, each taking parameters of different number or datatype.

    重载例子 :

    image

    image

    例如: 系统中的 TO_CHAR, 之类的,就是重载,可以接受不同参数。

    You must declare an identifier before using it. Therefore, a subprogram must be declared before calling it.

    ( 必须先声明,或者在 specification 中声明,或者在 body中声明,总之,真实定义之前必须要声明 )

    比如当系统在一个 procedure 中调用另一个 procedure , 但是,该 procedure 没有被声明或定义,那么它就不知道如何调用 ( 定义或声明要在这个 procedure 之前 )

    image

    calc_rating(), 被调用了,但是 它的定义在下边,所以就会出错。

    最好还是声明,因为如果两个 procedure 互相调用时,哪个放在前边也是不行的。

    image

    包中,函数 Functions 的限制 : ( 跟之前单体函数的限制差不多 )

    • A function called from a query or DML statement may not end the current transaction , create or roll back to a savepoint, or alter the system or session
    • A function called from a query statement or from a parallelized DML statement may not execute a DML statement or otherwise modify the database
    • A function called from a DML statement may not read or modify the particular table being modified by that DML statement.

    调用自己定义包中的函数

    SELECT taxes_pack.tax( salary ) , salary, last_name FROM employees; // taxes_pack 包名

    Oracle Supply package. ( 貌似只有少部分有用 )

    Most of the standard packages are created by running catproc.sql

    - 动态 ( 带参数的 SQL ) ( 顺序 : parse –> bind –> execute –> fetch )

       DBMS_SQL package 提供了 dynamic SQL .

       image

       例如 :

       image

       image

    - DBMS_DDL package

    - DBMS_JOB Subprograms

    - DBMS_OUTPUT

       PUT, NEW_LINE, PUT_LINE, GET_LINE, GET_LINES, ENABLE/DISABLE

       image


    1. 为什么使用包

    答:在一个大型项目中,可能有很多模块,而每个模块又有自己的过程、函数等。而这些过程、函数默认是放在一起的(如在PL/SQL中,过程默认都是放在一起的,即Procedures中),这些非常不方便查询和维护,甚至会发生误删除的事件。所以通过使用包就可以分类管理过程和函数。

    有点类似 object – c

    包分两部分,包规范包体

    2. 定义包说明
    说明
    3. 定义包体
    包体
    4. 使用包
    使用

    一、程序包的相关知识

    1.定义与说明
    a. 相关对象的封装
    b. 程序包的各部分
    - 程序包规格说明
    声明子程序
    - 程序包主体
    定义子程序
    2.使用程序包的优点
    - 模块化
    - 更轻松的应用程序设计
    - 信息隐藏
    - 新增功能
    - 性能更佳
    3.公有项和私有项的区别
    公有项:在程序包说明部分定义的变量、过程、函数
    私有项:在程序包主体部分定义的变量、过程、函数
    公有项 私有项
    可以在程序包之外引用 不能在程序包之外引用
    是在程序包规格说明中定义的 是在程序包主体中定义的
    用于全局目的 用于局部目的

    二、程序包创建说明

    1.程序包规格说明
    (1)、使用Create Package命令进行创建
    (2)、包含公用对象和类型
    (3)、声明类型、常量、变量、异常、游标和子程序
    (4)、可以在没有程序包主题的情况下存在
    (5)、可以重载
    - 程序包中的多个子程序可以具有相同的名称
    - 它们的形参是不同的
    - 只能位于打包的子程序中
    - 限制
    a. 如果子程序的参数仅名称或模式不同,则不能重载
    b. 不能基于其返回类型重载子程序
    2.程序包主体
    (1)、使用Create Package body 命令进行创建
    (2)、包含子程序和游标的定义
    (3)、包含私有声明
    (4)、不能在没有程序包规格说明的情况下独立存在
    3.程序包的调用
    包名.类型名;
    包名.函数名[参数表];
    包名..过程名[参数表];
    (1)、 Package-name.type-name
    (2)、 Package-name.object-name
    (3)、 Package-name.subprogram-name
    其中,Package-name 是程序包名称,type-name是类型名称,
    object-name是对象名称,subprogram-name 是子程序名称
    --示例
    DBMS_output.put_line(Hello);
    (4)、对于返回参数是游标类型的调用(如:引用游标)
    set autoprint on --打开Sqlplus输出
    variable tempCur RefCursor; --定义一个宿主类型的引用游标变量
    exec StudentPackage.ReturnStudent(:tempCur); --执行带有引用游标的过程 注意使用宿主类型的变量前面要加“:”符号
    4. 有关子程序和程序包的信息
    A.数据字典
    User_objects 用于检查对象是否存在
    User_source 用于获取对象的代码
    B. 包的修改和删除
    Alter Package [Body] 包名
    Alter Package Body StudentPackage;
    Drop Package [Body] 包名
    Drop Package Body StudentPackage;
    5. 创建格式
    A.创建包规格部分
    格式:Create [or replace] Package 包名
    IS|AS
    变量声明;
    类型定义;
    异常声明;
    游标声明;
    函数说明;
    过程说明;
    Pragma restrict_references(过程名或函数名,WNDS[,WNPS][,RNDS][,RNPS]) --编译指令 限定函数的操作
    End [包名];
    B.创建包主体部分
    格式: Create [or replace] package body 包主体名 --包主体名一定要是已经定义的包名
    IS|AS
    变量声明; --具体的实现部分
    类型定义;
    异常声明;
    游标声明;
    函数说明;
    过程定义;
    End [包主体名];

    6. 示例
    示例1.创建程序包的规格说明部分  

    --1
     1 Create or replace Package StudentPackage 
     2 is 
     3 Type curRefStudent is Ref Cursor Return Student%rowtype; 
     4 Procedure SelectStudent(FindID in Student.stuid%type); 
     5 Procedure InsertStudent(NewStudent in Student%rowType); 
     6 Procedure UpdateStudent(NewStudent in Student%rowType); 
     7 Procedure DeleteStudent(DelID in Student.stuid%type); 
     8 Procedure ReturnStudent(inOutstu in out curRefStudent); 
     9 Function RegurnRecordCount Return Number; 
    10 End studentPackage; 


    示例2.创建程序包的主体部分  

    --2
     1 Create or replace Package Body StudentPackage IS 
     2 Procedure SelectStudent (FindID in Student.stuid%type) as --注意没有Create 
     3 /*实现查询过程的定义*/ 
     4 Cursor findCur is select * from student where stuid=FindID; 
     5 Begin 
     6 For S in FindCur Loop 
     7 DBMS_output.put_line(S.stuID||' '||s.StuName||' '||S.Sex); 
     8 End Loop; 
     9 Exception 
    10 When No_Data_Found Then 
    11 DBMS_output.Put_Line('没有查到ID为'||FindID||'的记录!'); 
    12 When Others Then 
    13 DBMS_output.Put_Line('查询过程中发生意外情况'); 
    14 End SelectStudent; --结束查询过程 
    15 /*实现插入过程的定义*/ 
    16 Procedure InsertStudent(NewStudent in Student%rowType) as 
    17 iRec Integer; 
    18 Not_Exists_Student Exception; --预定义异常 
    19 Begin 
    20 Select count(*) into iRec from student where stuid=NewStudent.stuID; 
    21 IF iRec>0 Then 
    22 Raise Not_Exists_Student; 
    23 Else 
    24 insert into student values(NewStudent.stuid,NewStudent.stuName,NewStudent.sex); 
    25 commit; 
    26 End IF; 
    27 Exception 
    28 When Not_Exists_Student Then 
    29 DBMS_output.Put_Line('要插入的编号:'||NewStudent.stuid||'的记录已经存在'); 
    30 When Others Then 
    31 DBMS_output.Put_Line('插入记录操作过程中出现错误'); 
    32 End InsertStudent;--结束插入过程 
    33 /*实现更新过程的定义*/ 
    34 Procedure UpdateStudent(NewStudent in Student%rowType) as 
    35 iRec Integer; 
    36 Begin 
    37 select Count(*) into iRec From student Where stuid=NewStudent.stuid; 
    38 IF iRec =0 Then 
    39 DBMS_output.Put_Line('编号为:'||NewStudent.stuid||'的记录不存在,修改失败'); 
    40 ELSE 
    41 Update student Set Stuname=NewStudent.stuName,Sex=NewStudent.Sex 
    42 WHERE stuid=NewStudent.stuID; 
    43 Commit; 
    44 End IF; 
    45 Exception 
    46 When No_Data_Found Then 
    47 DBMS_output.Put_Line('编号为:'||NewStudent.stuID||'的记录不存在,修改失败'); 
    48 When Others Then 
    49 DBMS_output.Put_Line('执行修改操作时发生意外情况,修改未成功'); 
    50 End UpdateStudent;--结束修改过程 
    51 /*实现删除过程的定义*/ 
    52 Procedure DeleteStudent(DelID in Student.stuid%type) as 
    53 iRec Integer; 
    54 Begin 
    55 Select Count(*) into iRec From Student Where stuID=DelID; 
    56 IF iRec=0 Then 
    57 DBMS_output.Put_Line('编号为:'||DelID||'的记录不存在,删除操作时未成功'); 
    58 ELSE 
    59 Delete From student Where stuid=DelID; 
    60 Commit; 
    61 DBMS_output.Put_Line('删除成功!'); 
    62 End IF; 
    63 Exception 
    64 When Others Then 
    65 DBMS_output.Put_Line('执行删除操作时发生意外情况,删除未成功'); 
    66 End DeleteStudent; 
    67 /*实现参数带有游标类型定义*/ 
    68 Procedure ReturnStudent(inOutstu in out curRefStudent) as 
    69 Begin 
    70 Open inOutstu For Select * from student; 
    71 End ReturnStudent; 
    72 /*实现函数定义*/ 
    73 Function RegurnRecordCount Return Number as 
    74 RecCount number(10); 
    75 Begin 
    76 Select Count(*) into RecCount From student; 
    77 Return recCount; 
    78 Exception 
    79 When Others Then 
    80 DBMS_output.Put_Line('查询表中记录数时发生意外情况'); 
    81 End RegurnRecordCount; --结束函数的定义 
    82 End studentPackage;--结束包 


    示例3:调用包
    1. 调用studentPackage包中的InsertStudent过程  

    --invoke1
    1 Declare 
    2 newStu Student%RowType; 
    3 Begin 
    4 newStu.stuID:='1001'; 
    5 newStu.stuName:='张三'; 
    6 newStu.sex:=''; 
    7 studentPackage.InsertStudent(newStu); 
    8 End; 
    9 / 


    2. 调用studentPackage包中的UpdateStudent过程  

    --invoke2
     1 Declare 
     2 newStu Student%RowType; 
     3 Begin 
     4 newStu.stuID:='1001'; 
     5 newStu.stuName:='李四'; 
     6 newStu.sex:=''; 
     7 studentPackage.UpdateStudent(newStu); 
     8 Exception 
     9 When Dup_Val_On_Index Then 
    10 DBMS_output.Put_Line('唯一约束被破坏'); 
    11 When Others Then 
    12 DBMS_output.Put_Line('更新过程出现错误'); 
    13 End; 
    14 / 


    3. 调用studentPackage包中的DeleteStudent过程  

    --invoke3
    1 Begin 
    2 studentPackage.DeleteStudent('1001'); 
    3 End; 
    4 / 


    4. 调用studentPackage包中的ReturnRecordCount函数  

    --invoke4
    1 Begin 
    2 DBMS_output.put_Line(studentPackage.ReturnRecordCount); 
    3 End; 
    4 / 
  • 相关阅读:
    缓存一致性问题
    缓存雪崩
    mysql Replication机制
    数据库水平切分、拆库拆表
    mysql分表和分区实际应用简介
    mysql中间件
    mysql基础知识
    go语言redis使用(redigo)
    nginx location配置与rewrite配置
    PDO驱动使用
  • 原文地址:https://www.cnblogs.com/moveofgod/p/2778646.html
Copyright © 2011-2022 走看看