Fork me on GitHub

PL/SQL之包

1、包的定义

 一个包由两个独立的部分组成--包头和包体。给部分被单独地存放在数据字典中。
1.1定义包头
语法:
CREATE [OR REPLACE] PACKAGE [schema.] package
{IS|AS} 
    pl/sql_package;

package是包的名称
pl/sql_package可以是存储过程、函数、变量、类型、异常以及游标的定义。

存储过程或函数必须在包头中预定义。也就是说,在包头中定义存储过程名或函数名以及它们的参数,存储过程或函数的执行代码将在包体中定义。

CREATE OR REPLACE AuthsPack AS
    --获得auths表中作家的工资
    PROCEDURE QuerySalary(p_Code auths.author_code%TYPE,p_Salary auths.salary%TYPE);
    --向auths表插入记录
    PROCEDURE InsertAuthor(p_Code auths.author_code%TYPE,p_Name auths.name%TYPE);
END AuthsPack;

1.2定义包体
    包体是一个数据字典对象。只有在包头成功编译后,包体才能被编译。包体只包含包头中已预定义的子程序的代码。在包头中定义的对象可以直接在包体中使用,不必再包头中定义。
    
CREATE [OR REPLACE] PACKAGE BODY [schema.] package
{IS|AS}
    pl/sql_bady;

CREATE OR REPLACE PACKAGE BODY AuthsPack IS
    PROCEDURE QuerySalary(p_Code auths.author_code%TYPE,p_Salary auths.salary%TYPE)
    AS
        BEGIN
            SELECT salary INTO p_Salary
                FROM auths
                WHERE author_code= p_Code;
        END QuerySalary;
    PROCEDURE InsertAuthor(p_Code auths.author_code%TYPE,p_Name auths.name%TYPE);
    AS
        BEGIN
            INSERT INTO auths(author_code,name) VALUES(p_Code,p_Name);
        END InsertAuthor;
END AuthsPack;

    如果包头不包含存储过程和函数,则不必定义包体。如果包头中有预定义的子程序,则在包体中必须编写其子程序代码,而且包头和包体两部分指定的子程序必须一致,这包括相同的子程序名,参数名和参数类型。
    
1.3包的初始化
    与变量类似,包也可以被初始化。只是初始化部分在包体的最后部分被定义。

语法:
CREATE OR REPLACE PACKAGE BODY package {IS|AS}
    --包体中过程与函数的定义部分
BEGIN
    Initialization_code;--初始化代码
    --QuerySalary('A0001',v_Salary);
END [package]

2、包的使用

2.1包中对象的引用
    在包中定义的任意对象都可以再保外使用,只是在引用该对象前用包名做前缀。
    
--设置缓冲区大小
SET SERVEROUTPUT ON SIZE 100000
DECLARE
    v_Salary auths.salary%TYPE;
BEGIN
    AuthsPack.QuerySalary('A0001',v_Salary);
    DBMS_OUTPUT.PUT_LINE('工资为:');
    DBMS_OUTPUT.PUT_LINE(v_Salary);
END;

    此存储过程的调用有包名作前缀。包中存储过程的参数也可以有缺省值,这些参数可通过位置表示法或命名表示法来调用。在包体内部不必带包名前缀即可直接引用包头中的对象。

2.2重载包中的子程序
    在包的内部,存储过程和函数都可以被重载,这意味着有过个存储过程或函数可以使用同一个名称,但是参数不能相同。这样就允许用不同的参数调用同一个名字的过程或函数。
    
CREATE OR REPLACE AuthsPack AS
    PROCEDURE AddArticle(p_ArticleCode article.article_code%TYPE,
        p_AuthorCode article.author_code%TYPE);
    PROCEDURE AddArticle(p_Birthdate  article.birthdate%TYPE,
        p_ArticleCode article.article_code%TYPE);
END AuthsPack;

CREATE OR REPLACE PACKAGE BODY ArticlePack IS
    PROCEDURE AddArticle(p_ArticleCode article.article_code%TYPE,
        p_AuthorCode article.author_code%TYPE) AS
    BEGIN
        INSERT INTO Article(Article_code,Author_code) 
            VALUES(p_ArticleCode,p_AuthorCode);
    END AddArticle;
    PROCEDURE AddArticle(p_Birthdate article.birthdate%TYPE,
        p_ArticleCode article.article_code%TYPE) AS
    BEGIN
        INSERT INTO Article(Birthdate,Article_code) 
            VALUES(p_Birthdate,p_AuthorCode);
    END AddArticle;
END ArticlePack;

当仅仅参数名不同或者是模式不同时,不能重载子程序。
不能对仅有返回类型的函数进行重载。
重载函数的参数必须是数据类型不同或其类型间不可自动转换。

在定义包含违反上述限制的子程序的包时不会包编译错误。但是,允许PL/SQL引擎不能调用该子程序,会出现错误"PLS-307:too many daclarations of ’subprogram match this call."

3、在SQL语句中使用函数

  

  

  

  

  

  

4、系统提供的包DBMS_OUTPUT

  Oracle8中,系统提供了一些包,这些包时在安装Oracle时自动安装的,用户可以直接使用。在内嵌包中有一个包经常用到--DBMS_OUTPUT,现在来简单地学习一下它。

  内嵌包DBMS_OUTPUT用来输出PL/SQL变量的值。DBMS_OUTPUT包和其他系统包一样,都属于Oracle系统用户SYS内的对象。

  

  

posted @ 2015-08-21 16:12  何海洋  阅读(872)  评论(0编辑  收藏  举报