暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PL/SQL 之 程序包 和 动态SQL

晟数学院 2021-04-16
340
 

点击“蓝字”关注我们

晟数学院DBA成长日记--PL/SQL篇

包 Package

包是一种程序模块化设计的主要实现手段,通过包中可以将一个模块之中所要使用的各个程序结构(过程、函数、游标、类型、变量)放在一起进行管理,同时包中所定义的程序结构也可以方便的进行互调用。

包的基本概念

在Oracle之中如果要定义包则需要两个组成部分:

包规范(PACKAGE):

定义包中可以被外部访问的部分, 在包规范中声明的内容可以从应用程序和包的任何地方访问 ,其定义语法如下所示:

CREATE [REPLACE] PACKAGE 包名称

    [AUTHID CURRENT_USER | DEFINER]

    IS | AS

        结构名称定义(类型、过程、函数、游标、异常等)

END [包名称] ;

/


包体(PACKAGE BODY):

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

CREATE [REPLACE] PACKAGE BODY 包名称

    IS | AS

        结构实现(类型、过程、函数、游标、异常等)

    BEGIN

        包初始化程序代码 ;

    END [包名称] ;

/

(1)定义包规范

SCOTT@SDEDU> ed12501

create or replace package sdata_pkg

as

    function get_emp_fun(p_dno dept.deptno%type)

    return sys_refcursor; -- 返回弱游标类型

end;

/


SCOTT@SDEDU> @12501

Package created.


包的作用域

由于采用了包规范与包体相分离的方式,所以某些私有的操作就可以非常方便的进行定义(只要不在包规范中定义而包体定义的结构为私有)。而且在默认情况下,所有的包是在第一次被调用时才会进行初始化操作,而后包的运行状态保存到用户全局区的会话之中,在一个会话期间内,此包会一 直被用户所占用,一直到会话结束后才会将包释放。因此在包中的任何一个变量或游标等可以在一个会话期间一直存在,相当于全局变量,同时可以被所有的子程序所共享。

重载包中的子程序

如果一个包中定义了多个子程序,那么这些子程序是可以进行重载时,即:在一个包中可以同时存在一个以上具有相同名称但参数及个数不同的子程序。


包的初始化

在程序第一次调用数据包中的子程序、相关变量或者是类型引用时,就表示对包进行默认的实例化操作,此时会将包的内容从硬盘读入到内存,而此包将一直持续到整个会话结束。如果当某一会话第一次使用某个包时可以由用户定义制定一些属于自己的初始化操作,例如:为集合数据进行内容添充或者是一些更加复杂的业务功能。如果要编写包初始化的代码可以直接在包体中定义BEGIN语句,即, 在此部分编写初始化代码。

包的纯度级别

如果在包中定义了函数,那么可以直接通过SQL语句进行调用,如果现在要对包中的函数进行限制 ,例如:不能包含DML语句,如果要设置包的纯度级别可以使用如下语法完成:

PRAGMA RESTRICT_REFERENCES (函数名称 , WNDS [,WNPS] [,RNDS] [,RUPS]) ;

系统工具包

  • DBMS_JOB包

在Oracle的开发过程之中,经常需要为Oracle定义一些后台进程,以方便数据 库自动的执行某些操作。而要想实现这样的后台进程,则可以建立多个调度任务,而调度任务又被称为作业,读者可以直接利用DBMS_JOB包来实现。

  • DBMS_ASSERT包

在编写SQL语句过程之中,经常会出现一些敏感字符无 法使用,例如“‘”等。在Oracle中提供了 DBMS_ASSERT包,通过这些包,可以将字符串进行 转换。

  • DBMS_LOB包

DBMS_LOB包提供了大对象的操作支持,用户可 以直接利用此包实现对CLOB(大文本)或BLOB (二进制数据,例如:图片、音乐、文字等)类 型的列进行操作。

  • BFILE与DIRECTORY

如果要想实现文件的读取,那么还需要一种BFILE数据类型。BFILE 是外部大型对象(LOB),此数据类型存储在数据库表空间外的操 作系统文件中,BFILE提供了一个指向磁盘物理文件的一个定位器, 所以其只是只读数据,不参与事务处理。

动态SQL

动态SQL

在之前用户所编写的PL/SQL程序时有一个最大的特点:就是所操作的数据库对象(例如:表)必须存在,否则创建的子程序就会出现问题,而这样的操作在开发之中被称为静态 SQL操作,而动态SQL操作可以让用户在定义程序时不指定具体的操作对象,而在执行时动态的传入所需要的数据库对 象,从而使程序变得更加的灵活。

(2)利用动态SQL再执行时创建一张数据表

SCOTT@SDEDU> ed12504

--利用动态SQL再执行时创建一张数据表

create or replace function         

    get_table_count_fun(p_table_name varchar2)

    return

number as

    v_sql_statement    varchar2(200);

    v_count                    number;

begin

    select count(*) into v_count from user_tables where table_name=upper(p_table_name);

    if v_count=0 then

    v_sql_statement:='create table'||p_table_name||'

    (

        id number primary key,

        name varchar2(30) not null,

    )';

        execute immediate v_sql_statement;

    end if;

        v_sql_statement:='select count(*) from'||p_table_name;

        execute immediate v_sql_statement into v_count;

    return v_count;

end;

/


SCOTT@SDEDU> @12504

Function created.


注意:如果程序不能执行,可能是没有开放 create table 权限:GRANT CREATE ANY TABLE TO scott ;

EXECUTE IMMEDIATE 语句

在动态SQL之中EXECUTE IMMEDIATE是最为重要的执行命令,使用此语句可以方便的在PL/SQL程序之中执行DML( INSERT、UPDATE、DELETE、单列SELECT)、DDL( CREATE、ALTER、DROP)、DCL(GRANT、REVOKE)语句。

EXECUTE IMMEDIATE语法定义如下所示:

EXECUTE IMMEDIATE 动态SQL字符串 [[BULK COLLECT]

INTO 自定义变量 , .... | 记录类型]

[USING [IN | OUT | IN OUT] 绑定参数 , ...]

[[RETURNING | RETURN] [BULK COLLECT] INTO 绑定参 数 , ...] ;


在EXECUTE IMMEDIATE由以下三个主要子句组成:

  • INTO:保存动态SQL执行结果,如果返回多行记录可 以通过BULK COLLECT设置批量保存; 

  • USING:用来为动态SQL设置占位符设置内容;

  • RETURNING | RETURN:两者使用效果一样,是取得 更新表记录被影响的数据,通过BULK COLLECT来 设置批量绑定。


推荐阅读

PL/SQL 之 触发器(下篇)

晟数学院DBA成长日记

PL/SQL 之 触发器(上篇)

晟数学DBA成长

PL/SQL 之 子程序(下篇)

晟数学DBA成长

记得长按上方二维码关注我们~
文章转载自晟数学院,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论