PL/SQL-->包的创建与管理

PL/SQL-->包的创建与管理

      包,是一个逻辑集合,是PL/SQL类型、PL/SQL项以及PL/SQL子程序的集合。PL/SQL类型包括table类型,record类型。PL/SQL项则包括游标,游标变量。PL/SQL子程序包括过程,函数等。可以说包可谓是包罗万象。包是所有PL/SQL相关资源的汇总。

      包的使用可以简化应用程序设计,实现信息掩藏,子程序重载等功能。

      包的优点
              1.模块化:将函数,子程序全部融合在一起,使得成为一个有机的整体,封装了相关的结构。
              2.易于维护:整合了子程序,更易于维护。
              3.简化应用程序设计:包的声明与包体内容相分离。
              4.隐藏信息:私有对象不可访问,所有的包体内代码可以实现隐藏。
              5.节省I/O:一次编译,多次使用。


一、包的组成与创建语法

      包头:用于定义包的公共组件,如函数头,过程头,游标以及常量,变量等。包头中定义的公共组件可以在包内引用,也可以被其它子程序引用。

      包体:用于定义包头中定义过的过程和函数。包体内可以单独定义私有组件,包括变量,常量,过程和函数等。私有组件只能在包内使用,而不能被其它子程序所调用。

              一言以蔽之,包头定义包的声明及描述部分,而包体则定义了对应包的具体执行部分。

      创建包的语法:

              CREATE [OR REPLACE] PACKAGE package_name        --定义包头
              {AS|IS}
                      public_variable_declarations |
                      public_type_declarations |
                      public_exception_declarations |  
                      public_cursor_declarations |
                      function_declarations |
                      procedure_specifications
              END [package_name]  
   

              CREATE [OR REPLACE] PACKAGE BODY package_name    --定义包体,包体中的package_name应当与包头中的package_name相同
              {AS|IS}  
                      private_variable_declarations |
                      private_type_declarations |
                      private_exception_declarations |
                      private_cursor_declarations |  
                      function_declarations |
                      procedure_specifications  
              END [package_name]  


二、创建包               

      下面演示包的创建,基于用户scott创建,存储过程,函数等依赖于其下的对象

      1.创建包头

              CREATE OR REPLACE PACKAGE emp_package IS      --创建包头,包的名字为emp_package
                      g_deptno NUMBER(3) := 30;                            --定义一个公共变量g_deptno
                      PROCEDURE add_employee(eno NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT g_deptno); --声明过程
                      PROCEDURE fire_employee(eno NUMBER);                                                                                                                    --声明过程
                      FUNCTION get_sal(eno NUMBER) RETURN NUMBER;                                                                                                      --声明函数
              END emp_package;
              /

      2.创建包体  

              CREATE OR REPLACE PACKAGE BODY emp_package IS      --创建包体,注意,包体中包的名字必须与包头的名字相一致
           
                      FUNCTION validate_deptno(v_deptno NUMBER) RETURN BOOLEAN  --创建一个私有函数,注:此私有函数不能被该包外子程序调用
                      IS
                              v_temp INT;
                      BEGIN
                              SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;
                              RETURN TRUE;
                      EXCEPTION
                              WHEN NO_DATA_FOUND THEN
                                      RETURN FALSE;
                      END;

                      PROCEDURE add_employee    --创建添加雇员的过程
                              (eno NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT g_deptno) IS
                      BEGIN
                              IF validate_deptno(dno) THEN    --该过程调用了包内的一个函数validate_deptno来验证dno的有效性
                                      INSERT INTO emp(empno, ename, sal, deptno) VALUES(eno, name, salary, dno);
                              ELSE
                                      RAISE_APPLICATION_ERROR(-20000, '不存在该部门');
                              END IF;
                      EXCEPTION
                              WHEN DUP_VAL_ON_INDEX THEN
                                      RAISE_APPLICATION_ERROR(-20011, '该雇员已存在');
                      END;

                      PROCEDURE fire_employee(eno NUMBER) IS  --创建解除雇员的过程
                      BEGIN
                              DELETE FROM emp WHERE empno = eno;
                              IF SQL%NOTFOUND THEN
                                      RAISE_APPLICATION_ERROR(-20012, '该雇员不存在');
                              END IF;
                      END;

                      FUNCTION get_sal(eno NUMBER) RETURN NUMBER IS  --创建函数get_sal返回雇员的薪水
                              v_sal emp.sal%TYPE;
                      BEGIN
                              SELECT sal INTO v_sal FROM emp WHERE empno = eno;
                              RETURN v_sal;
                      EXCEPTION
                              WHEN NO_DATA_FOUND THEN
                                      RAISE_APPLICATION_ERROR(-20012, '该雇员不存在');
                      END;
              END emp_package;
              /

      3.创建仅包含包头的包(仅包含包头的包也可以被调用,具体参照后面的包的调用)

              CREATE OR REPLACE PACKAGE global_int
              IS
                  g_positive  CONSTANT NUMBER:=10;
                  g_negative CONSTANT NUMBER:=-10;
              END global_int;


三、包的调用

              包的私有对象只能在包内调用。如上面的例子中对包内私有函数validate_deptno进行了直接调用

              包的公共对象,既可以在包内调用,也可以由其他应用程序调用。使用其他应用程序调用时的方法:包名.包对象

      1.调用包的公共变量

              scott@ORCL> exec emp_package.g_deptno:=10;

             
      2.调用包的公共过程

              scott@ORCL> exec emp_package.add_employee(2222,'Robinson',3000); --此调用未指定部门号,则使用缺省值,但前面执行了
                                                                                                                                                --exec emp_package.g_deptno:=10;故部门号变为10                                         
              scott@ORCL> exec emp_package.add_employee(3333,'Jackson',4000,20);

              scott@ORCL> select * from emp where empno in(2222,3333);

                        EMPNO ENAME          JOB                          MGR HIREDATE                SAL            COMM        DEPTNO
              ---------- ---------- --------- ---------- --------- ---------- ---------- ----------
                          2222 Robinson                                                                              3000                                      10
                          3333 Jackson                                                                                4000                                      20           

                   
      3.调用包的公共函数

              scott@ORCL> var sal number
              scott@ORCL> exec :sal:=emp_package.get_sal(7788);
              PL/SQL procedure successfully completed.

              scott@ORCL> print sal

                            SAL
              ----------
                          310           

                   
      4.以不同用户身份调用包.需要使用schema名字来调用,即:用户名.包名.包对象名

              scott@ORCL> conn lion/lion    --注意帐户需要具有执行所调用包的权限

              lion@ORCL> exec scott.emp_package.fire_employee(2222);         


      5.调用远程数据库包的公共对象。调用方法:包名.包对象名@数据库链接名

              sys@ASMDB> create database link orcl
                  connect to lion identified by lion
                  using 'orcl';

              Database link created.

              sys@ASMDB> exec scott.emp_package.add_employee@orcl(4444,'Richard',4000);

              BEGIN scott.emp_package.add_employee@orcl(4444,'Richard',4000); END;
                          *
              ERROR at line 1:
              ORA-06550: line 1, column 7:    --注意远程调用时,对于缺省的参数不适用,需要明确指定参数
              PLS-00424: RPC defaults cannot include Package State
              ORA-06550: line 1, column 7:
              PL/SQL: Statement ignored   

              sys@ASMDB> exec scott.emp_package.add_employee@orcl(4444,'Richard',4000,20);  --调用被成功执行

              PL/SQL procedure successfully completed.

           
      6.无包体包的调用(使用前面创建的包global_int)     

              scott@ORCL> BEGIN
                  DBMS_OUTPUT.PUT_LINE('Result is : '||2*global_int.g_positive); --使用包DBMS_OUTPUT来调用
                  END;
                  /

              Result is : 20

              PL/SQL procedure successfully completed.     

           
              scott@ORCL> CREATE OR REPLACE FUNCTION f_negative(m number)    --将包嵌入到函数之中
                  RETURN NUMBER
                  IS
                  BEGIN
                      RETURN(m*global_int.g_negative);
                  END f_negative;
                  /

              Function created.

              scott@ORCL> EXEC DBMS_OUTPUT.PUT_LINE(f_negative(2));
           
              -20

              PL/SQL procedure successfully completed.

           
四、包的管理

      1.查看包

              scott@ORCL> select line,text from user_source              --查看包头
                  where name='EMP_PACKAGE' and type='PACKAGE';

                          LINE TEXT
              ---------- ------------------------------------------------------------
                                1 PACKAGE emp_package IS
                                  g_deptno NUMBER(3) := 30;
                                  PROCEDURE add_employee(eno NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT g_deptno);
                                  PROCEDURE fire_employee(eno NUMBER);
                                  FUNCTION get_sal(eno NUMBER) RETURN NUMBER;
                                6 END emp_package;


              scott@ORCL> select line,text from user_source        --查看包体
                  where name='EMP_PACKAGE' and type='PACKAGE BODY';

                          LINE TEXT
              ---------- --------------------------------------------------------------------------------
                                1 PACKAGE BODY emp_package IS
                                  FUNCTION validate_deptno(v_deptno NUMBER) RETURN BOOLEAN IS
                                      v_temp INT;
                                  BEGIN
                                      SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;
                                      RETURN TRUE;
                                                      ......................
                               

      2.查看包的参数

              scott@ORCL> desc emp_package;

              PROCEDURE ADD_EMPLOYEE
                Argument Name                                  Type                                      In/Out Default?
                ------------------------------ ----------------------- ------ --------
                ENO                                                      NUMBER                                  IN
                NAME                                                    VARCHAR2                              IN
                SALARY                                                NUMBER                                  IN
                DNO                                                      NUMBER                                  IN        DEFAULT

              PROCEDURE FIRE_EMPLOYEE
                Argument Name                                  Type                                      In/Out Default?
                ------------------------------ ----------------------- ------ --------
                ENO                                                      NUMBER                                  IN

              FUNCTION GET_SAL RETURNS NUMBER
                Argument Name                                  Type                                      In/Out Default?
                ------------------------------ ----------------------- ------ --------
                ENO                                                      NUMBER                                  IN
 

      3.包的删除

              DROP PACKAGE package_name    --同时删除包体和包头

              scott@ORCL> DROP PACKAGE global_int;

              删除包体,保留包头

                      DROP PACKAGE BODY package_name    --删除包体
                 
              scott@ORCL> drop package body emp_package;
              Package body dropped.


      4.包的编译

                  重新编译包规范和包体:alter package...compile
                  重新编译包规范:alter package...compile specification
                  重新编译包体:alter package...compile body
     

五、总结

      创键包体之前应该先创建包头

      包头应当仅仅包含那些希望作为公共对象的部分

      包头的声明应包含尽可能少的结构信息

      任意包头的变更,需要重新编译该包内的子程序

      在包头内定义的任意公共对象可以被任意内部或外部子程序调用

      包体内的私有对象仅仅能被该包体内的子程序调用

转自:http://blog.csdn.net/robinson_0612/article/details/6084475
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值