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;故部门号变为

        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

          2  connect to lion identified by lion

          3  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

          2  DBMS_OUTPUT.PUT_LINE('Result is : '||2*global_int.g_positive); --使用包DBMS_OUTPUT来调用

          3  END;

          4  /

        Result is : 20

 

        PL/SQL procedure successfully completed.   

           

        scott@ORCL> CREATE OR REPLACE FUNCTION f_negative(m number)   --将包嵌入到函数之中

          2  RETURN NUMBER

          3  IS

          4  BEGIN

          5    RETURN(m*global_int.g_negative);

          6  END f_negative;

          7  /

 

        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        --查看包头

          2  where name='EMP_PACKAGE' and type='PACKAGE';

 

              LINE TEXT

        ---------- ------------------------------------------------------------

                 1 PACKAGE emp_package IS

                 2   g_deptno NUMBER(3) := 30;

                 3   PROCEDURE add_employee(eno NUMBER, name VARCHAR2, salary N

                   UMBER, dno NUMBER DEFAULT g_deptno);

 

                 4   PROCEDURE fire_employee(eno NUMBER);

                 5   FUNCTION get_sal(eno NUMBER) RETURN NUMBER;

                 6 END emp_package;

 

           

        scott@ORCL> select line,text from user_source     --查看包体

          2  where name='EMP_PACKAGE' and type='PACKAGE BODY';

 

              LINE TEXT

        ---------- --------------------------------------------------------------------------------

                 1 PACKAGE BODY emp_package IS

                 2   FUNCTION validate_deptno(v_deptno NUMBER) RETURN BOOLEAN IS

                 3     v_temp INT;

                 4   BEGIN

                 5     SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;

                 6     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

      

五、总结

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

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

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

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

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

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

   

六、更多参考

有关SQL请参考

        SQL 基础--> 子查询

        SQL 基础-->多表查询

SQL基础-->分组与分组函数

SQL 基础-->常用函数

SQL 基础--> ROLLUP与CUBE运算符实现数据汇总

SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)

 

    有关PL/SQL请参考

        PL/SQL --> 语言基础

PL/SQL --> 流程控制

PL/SQL --> 存储过程

PL/SQL --> 函数

PL/SQL --> 游标

PL/SQL -->隐式游标(SQL%FOUND)

PL/SQL --> 异常处理(Exception)

PL/SQL --> PL/SQL记录

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

PL/SQL --> 包重载、初始化

PL/SQL --> DBMS_DDL包的使用

PL/SQL --> DML 触发器

PL/SQL --> INSTEAD OF 触发器

 

 

       

时间: 2024-12-03 20:51:41

PL/SQL --> 包的创建与管理的相关文章

PL/SQL9——包的创建与管理

http://blog.csdn.net/robinson_0612/article/details/6084475     包,是一个逻辑集合,是由PL/SQL类型以及PL/SQL子程序的集合.PL/SQL类型包括table类型,record类型.PL/SQL项则包括游标,游标 变量.PL/SQL子程序包括过程,函数等.可以说包可谓是包罗万象.是所有PL/SQL相关资源的汇总.     包的使用可以简化应用程序设计,实现信息掩藏,子程序重载等功能.     包的优点         1.模块化

PL/SQL --> 包重载、初始化

--========================== -- PL/SQL --> 包重载.初始化 --==========================       包的重载功能类似于C++中函数的重载功能,即拥有多个同名的子程序,每个同名子程序使用不同的参数.用户可以传递不同的参数来调 用同名但参数不同的子程序,此即为包的重载功能.简言之,不管传递什么样的参数,所完成的任务是相同的.假定需要查询部门所在的位置 ,输入参数部门编号或部门名称都会返回同样的结果.对外部程序而言,似乎是调用的同

MS SQL基础教程:创建和管理视图

13.10.1 创建视图 SQL SERVER 提供了使用SQL SERVER Enterprise Manager 和Transac-SQL 命令两种方法来创建视图.在创建或使用视图,时应该注意到以下情况: •只能在当前数据库中创建视图,在视图中最多只能引用1024 列: •如果视图引用的表被删除,则当使用该视图时将返回一条错误信息,如果创建具有相同的表的结构新表来替代已删除的表视图则可以使用,否则必须重新创建视图: •如果视图中某一列是函数.数学表达式.常量或来自多个表的列名相同,则必须为列

PL/SQL --> DBMS_DDL包的使用

--============================= -- PL/SQL --> DBMS_DDL包的使用 --=============================       为了便于建立性能良好的PL/SQL程序,Oracle提供了大量的系统包供使用.Oracle提供的这些包扩展并增强了数据库的一些功能,以及突 破了PL/SQL的一些限制.本文讲述了Oracle提供的包DBMS_DDL,以及其使用方法.   一.    使用DBMS_DDL包可以对包,包体,存储过程,函数,触

使用PL/SQL developer 查看创建一张表的SQL语句

我们在使用PL/SQL developer中想创建一张表的SQL语句,该如何查看呢? 其实很简单的,我们只需要找到该表,然后右键–"DBMS_元数据"-"DDL",如下图:

PL/SQL --> DML 触发器

--======================= -- PL/SQL --> DML 触发器 --=======================         何谓触发器?简言之,是一段命名的PL/SQL代码块,只不过该代码块在特定的条件下被触发并且执行.对于这样的代码我们称之为触发器 .触发器根据触发类型的不同又分为不同级别的触发器,下面将给出触发器的分类,定义,以及使用的示例.   一.触发器的相关概念     1.触发器的分类         通常根据触发条件以及触发级别的不同分为DM

PL/SQL --> INSTEAD OF 触发器

--============================== -- PL/SQL --> INSTEAD OF 触发器 --==============================       INSTEAD OF 触发器常用于管理编写不可更新的视图,INSTEAD-OF触发器必须是行级的.     可以用INSTEAD OF触发器来解释INSERT.UPDATE和DELETE语句,并用备用的程序代码替换那些指令.   一.不可更新视图     基于下列情形创建的视图,不可直接对其进行D

PL/SQL --> 函数

--================== -- PL/SQL --> 函数 --==================       函数通常用于返回特定的数据.其实质是一个有名字的PL/SQL块,作为一个schema对象存储于数据库,可以被反复执行.函数通常被作为 一个表达式来调用或存储过程的一个参数,具有返回值.   一.建立函数的语法     CREATE [ OR REPLACE ] FUNCTION function_name         (argument1 [mode1] data

PL/SQL --> 异常处理(Exception)

--================================ -- PL/SQL --> 异常处理(Exception) --================================           Exception是一种PL/SQL标识符,当运行的PL/SQL块出现错误或警告,则会触发异常处理.为了提高程序的健壮性,可以在PL/SQL块中引 入异常处理部分,进行捕捉异常,并根据异常出现的情况进行相应的处理.   一.异常的类型      ORACLE异常分为两种类型:系统