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 / 
  • 相关阅读:
    HDU 4472 Count DP题
    HDU 1878 欧拉回路 图论
    CSUST 1503 ZZ买衣服
    HDU 2085 核反应堆
    HDU 1029 Ignatius and the Princess IV
    UVa 11462 Age Sort
    UVa 11384
    UVa 11210
    LA 3401
    解决学一会儿累了的问题
  • 原文地址:https://www.cnblogs.com/moveofgod/p/2778646.html
Copyright © 2011-2022 走看看