Oracle12C--包(四十七)

xiaoxiao2021-02-27  131

知识点的梳理: 通过包可以实现多种程序结构的统一管理,包分为两个部分,即包规范,包体,只有在包规范中定义的程序结构才可以被其他程序所使用;包中的子程序支持重载,只需要考虑参数以及个数的不同即可; 包中程序的纯度有4 种级别:WNDS,RNDS,WNPS,RNPS

  

包的基本概念 包是一种程序模块化设计的实现手段。通过包将一个模块所需要的程序(过程,函数,游标,类型)结构统一管理,同时包与包之间也可以互相调用; 定义包需要两个组成部分: 包规范(PACKAGE):定义包中可以被外部访问的部分,在包规范中声明的内容可以从应用程序和包的任何地方访问,语法:

CREATE OR [REPLACE] PACKAGE 包名称 [AUTHID CURRENT_USER | DEFINER] IS | AS 结构名称定于(类型,过程,函数,游标,异常等) END [包名称]; /

[AUTHID CURRENT_USER | DEFINER]为权限设置,

如果包规范中的某个操作可以由使用者权限决定,则将其设置为CURRENT_USER, 在包规范中所定义的所有子程序权限必须与包规范声明时定义的权限相同  

包体(PACKAGE BODY):负责包规范中定于的函数或过程的具体实现代码,如果在包体中定义了包规范中没有的内容,则此部分内容将被设置为私有访问,包体的定义语法如下:

CREATE OR [REPLACE] PACKAGE BODY 包名称 IS |AS 结构实现(类型,过程,函数,游标,异常等) BEGIN 包初始化程序代码; END [包名称]; /

示例1:定义包规范

CREATE OR REPLACE PACKAGE mldn_pkg

AS

FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN SYS_REFCURSOR ; --返回弱游标类型

END ;

/

分析: 定义了一个包规范,此规范定义了一个get_emp_fun()函数,该函数可被任何应用程序调用,该函数的返回值类型为SYS_REFCURSOR

方法2:自己定义弱类型游标

CREATE OR REPLACE PACKAGE mldn_pkg

AS

TYPE cursor_ref IS REF CURSOR ;

FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN cursor_ref ;

END ;

/

  

示例2:定义包体实现get_emp_fun()函数

CREATE OR REPLACE PACKAGE BODY mldn_pkg

AS

FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN SYS_REFCURSOR

AS

cur_var SYS_REFCURSOR ;

BEGIN

OPEN cur_var FOR SELECT * FROM emp WHERE deptno=p_dno ; --打开参数游标

RETURN cur_var ;

END ;

END ;

/

方法2:自定义游标变量

CREATE OR REPLACE PACKAGE BODY mldn_pkg

AS

FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN cursor_ref

AS

cur_var cursor_ref ;

BEGIN

OPEN cur_var FOR SELECT * FROM emp WHERE deptno=p_dno ; --打开参数游标

RETURN cur_var ;

END ;

END ;

/

通过user_objects与user_source查询包的信息 示例1:查询user_objects数据字典确认包规范及包体信息

SELECT object_type , object_name , status FROM user_objects

WHERE object_type IN ('PACKAGE','PACKAGE BODY') ;

示例2:查询user_source数据字典,查看包规范

SELECT *

FROM user_source

WHERE type='PACKAGE' AND name='MLDN_PKG' ;

包的调用 示例1:定义PL/SQL程序块调用包中的函数

DECLARE

v_receive SYS_REFCURSOR ;

v_empRow emp%ROWTYPE ; --定义行类型

BEGIN

v_receive := mldn_pkg.get_emp_fun(10) ;

LOOP

FETCH v_receive INTO v_empRow ; --取得游标数据

EXIT WHEN v_receive%NOTFOUND ; --如果没有数据则退出

DBMS_OUTPUT.put_line('雇员姓名:' || v_empRow.ename || ',雇员职位:' || v_empRow.job) ;

END LOOP ;

END ;

/

  

示例2:如果不使用SYS_REFCURSOR,则在声明v_receive变量时,就需要通过包定义类型

DECLARE

v_receive mldn_pkg.cursor_ref ;

v_empRow emp%ROWTYPE ; --定义行类型

BEGIN

v_receive := mldn_pkg.get_emp_fun(10) ;

LOOP

FETCH v_receive INTO v_empRow ; --取得游标数据

EXIT WHEN v_receive%NOTFOUND ; --如果没有数据则退出

DBMS_OUTPUT.put_line('雇员姓名:' || v_empRow.ename || ',雇员职位:' || v_empRow.job) ;

END LOOP ;

END ;

/

  

删除包 删除包规范语法:

DROP PACKAGE 包名称;

删除包体

DROP PACKAGE BODY 包名称;

示例1:删除mldn_pkg包

DROP PACKAGE mldn_pkg ;

此时删除的是包规范,删除的同时包体会一并删除

重新编译包 语法:

ALTER PACKAGE 包名称 COMPILE [DEBUG] PACKAGE | SPECIFICATION | BODY [REUSE SETTINGS];

包的重新编译有3种编译形式:

PACKAGE

重新编译包规范和包体

SPECIFICATION

重新编译包规范

BODY

重新编译包体

示例1重新编译包规范

ALTER PACKAGE mldn_pkg COMPILE SPECIFICATION ;

示例2重新编译包体

ALTER PACKAGE mldn_pkg COMPILE BODY ;

  

转载请注明原文地址: https://www.6miu.com/read-13612.html

最新回复(0)