plsql 如何创建包package?

1.情景展示

在Oracle当中,当遇到负责的业务逻辑时,我们可能会需要写多个存储过程;

如果这些存错过程又有依赖关系,比如说:B存储过程只能等到A存储过程执行完毕才能执行,如何实现?

2.具体分析

在Oracle当中,也有包package的概念,我们可以将多个存储过程交由包来统一管理。

包结构如下:

常用的就是:Functions、Procedures、Types、Variables、Constants和Exceptions。

说明:

PACKAGE由PACKAGE和PACKAGE BODY构成;

具体的代码实现,需要写在PACKAGE BODY当中(比如:存储过程)。

PACKAGE BODY当中的内容可以相互访问,比如:在B存储过程当中可以调用A存储过程。

如果需要外界调用的话,必须在PACKAGE当中声明,外部才能访问得到。

3.解决方案

打开plsql,在对象窗口当中,找到Packages;

右键--》新建;

给包起个名字,最好以PKG_开头,方便我们识别。

生成的默认格式如下:

tyepe、constant、variable和function,我们都用不到,直接删掉;

点击左上角的运行按钮;

PKG_TEST将会创建成功,并且会自动为PKG_TEST创建PACKAGE BODY;

此时,报错信息不用担心,将多余的代码全部删除;

再次点击左上角的执行按钮,PKG_TEST的body就会创建成功。

这个里面可以写多个存储过程。

需要注意的是:

脚本需要写在PACKAGE BODY里面,并且查看或者编辑的时候,我们也只能通过PACKAGE BODY。

如果这些存储过程需要外部能够调用得到的话,需要我们在PACKAGE当中引入它们。

也就是说,要想通过外界访问得到的内容,需要在放在PACKAGE当中进行声明。

 

5.如何调用?

以存储过程为例;

既可以查看/编辑PACKAGE,也可以查看/编辑PACKAGE BODY。

点击要执行的存储过程,右键,测试;

打开测试窗口,进行存储过程调用测试即可。

具体用法见文末推荐。

4.扩展延伸

通常情况下,当我们在PACKAGE BODY当中,创建多个存储过程后,我们往往还会额外创建一个存储过程;

这个存储过程里面调用其它需要执行的存储过程;

查看代码
create or replace package body PKG_TEST is

  procedure PRO_TEST1(IN_FRCODE VARCHAR2) is
  begin
    delete FROM BASE_ORG_INFO WHERE AREA = IN_FRCODE;
    commit;
  end;
  procedure PRO_TEST2(IN_FRCODE VARCHAR2) is
  begin
    delete FROM BASE_ORG_INFO WHERE AREA = IN_FRCODE;
    commit;
  end;
  procedure PRO_TEST3(IN_FRCODE VARCHAR2) is
  begin
    delete FROM BASE_ORG_INFO WHERE AREA = IN_FRCODE;
    commit;
  end;
  
  /*统一管理要调用的存储过程,并决定存储过程的执行顺序。*/
  procedure PRO_MAIN(IN_FRCODE VARCHAR2) is
  begin
    --调用内部存储过程
    PRO_TEST1(IN_FRCODE);
    PRO_TEST2(IN_FRCODE);
    PRO_TEST3(IN_FRCODE);
  end;
end PKG_TEST;

然后,仅仅将该存储过程通过PACKAGE暴露出去,供外部调用。

查看代码
create or replace package PKG_TEST is

  -- Author  : MARYDON
  -- Created : 2022/3/11 9:52:57
  -- Purpose : 测试包
  -- 声明在这里的存储过程外界可以通过包名进行调用
  /*将主存储过程暴露出去,供外部调用*/
  procedure PRO_MAIN(IN_FRCODE VARCHAR2);
end PKG_TEST;

这样一来,不仅提高了安全性、可维护性和可扩展性,调用方也不需要关注里面的内部实现,对双方而言都有好处,这其实是java当中的封装特性。

2022年3月14日18:41:37

我们知道,现在可以调用PKG_TEST.PROMAIN(),传入参数完成调用;

如果我们需要调用多次话,可以使用定时器创建定时执行任务。

定时任务可以解决同一个参数值多次调用的问题

但是,无法解决传多个不同值调用的问题,除了创建不同定时器这种笨方法外,我们还可以:

多个不同值之间使用逗号隔开,然后在调用的main()当中,循环调用。

/*统一管理要调用的存储过程*/
  procedure PRO_MAIN(IN_FRCODE VARCHAR2) is
    v_level number;
  
  begin
    --统计逗号个数
    select lengthb(translate(in_frcode, ',' || in_frcode, ','))
      into v_level
      from dual;
    --将in_frcode按逗号拆分,放到游标当中,循环调用
    for cur_frcode in (select regexp_substr(in_frcode,
                                            '[^,]+',
                                            1,
                                            level,
                                            'i') frcode
                         from dual
                       connect by level <= v_level + 1) loop
    
      --调用内部存储过程
      PRO_TEST1(cur_frcode.frcode);
      PRO_TEST2(cur_frcode.frcode);
      PRO_TEST3(cur_frcode.frcode);
    end loop;
  end;

定期器当中指定入参时,按照逗号将多个frcode隔开即可。

5.异常

2022年3月14日17:19:38

如果,在保存包体PACKAGE BODY时,出现形如:xxx is declared in a package specification and must be defined in the package body的错误。

这是因为PACKAGE 当中对于该存储过程的声明与在PACKAGE BODY当中的定义,不完全一致导致的。

写在最后

  哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

 相关推荐:

posted @ 2022-03-11 15:50  Marydon  阅读(2033)  评论(0编辑  收藏  举报