LightDB支持存储过程,除了支持Postgres的plpgsql存储过程,还兼容Oracle的存储过程,新增了plorasql过程语言。上一篇中我们介绍了存储过程中的子程序,这一篇主要讲述存储过程中的包。
包用于将相关的PL/SQL元素(过程、函数、变量、常量、自定义数据类型、游标等)组织在一起,作为一个完整的逻辑单元,编译后存储在数据库服务器中,作为一种全局的模式对象,供应用程序共享。
包由包规范和包体两部分组成,在数据库中独立存储。其中包规范声明了包中的所有公共元素,这些公共元素可以在包的外部被引用。如果包规范中声明了存储过程,则需要在包体中实现。在包体中,还可以定义私有元素,这些私有元素只能在包内部引用,而不能在包的外部引用。
除了包规范和包体的概念,还有内置包、用户包的区别,内置包不是用户定义的包,而是数据库本身提供的,用户可以不用创建,直接调用内置包。LightDB中本身也提供部分内置包,可以到官网去查看。而用户包就是用户自己创建的包。
好了,下面我们看一下如何创建包吧。
创建包可通过CREATE PACKAGE 语法创建,包括创建包规范,创建包体两部分。其中,包规范声明了包中的公共元素,如过程、函数、游标、数据类型、变量等。这些公共元素的作用域为包所在的模式。在包规范中声明的元素不仅可以在包的内部使用,也可以被应用程序调用。另外包可以支持重载子程序(即包中的子程序允许具有相同的名称,但具有不同的形式参数)。
示例如下:
create or replace package changan -- CREATE PACKAGE 创建包规范
is
procedure shenlan; -- 声明一个存储过程
end;
/
create or replace package body changan -- CREATE PACKAGE BODY 创建包体
is
procedure shenlan
is
begin
raise notice 'hello changan shenlan sl03';
end;
end;
end;
/
包中支持重载子程序:
create or replace package changan -- CREATE PACKAGE 创建包规范
is
procedure shenlan; -- 声明一个存储过程
procedure shenlan(a int); -- 重载子程序
end;
/
create or replace package body changan -- CREATE PACKAGE BODY 创建包体
is
procedure shenlan
is
begin
raise notice 'hello changan shenlan sl03';
end;
end;
procedure shenlan(a int) -- changan为模式名,shenlan为存储过程名
is
begin
raise notice '%', a; -- 通过下标访问联合数组
end;
end;
/
其中, OR REPLACE表示如果包已经存在,则重建包。如果包规范中声明了游标或子程序,那么必须创建对应的包体,否则包体是可选的。包体与包规范必须同名且放在同一个模式中。
create or replace package changan
is
TYPE xxRec IS RECORD (x char, y int); -- 类型定义
-- 没有子程序以及游标,不必创建包体
end;
/
包体中还可以包含包规范中没有声明的变量、游标、类型、过程和函数等,但他们是私有元素,只能由同一包中的过程或函数使用。示例如下:
create or replace package pkgtb
as
procedure show;
procedure show(a int);
end;
/
create or replace package body pkgtb
as
v int := 10;
procedure show
is
begin
for v in (select b from t1) loop
raise notice 'show1: %', v;
end loop;
end;
procedure show(a int)
is
begin
for v in (select b from t1) loop
raise notice 'show2: %', v;
end loop;
end;
procedure privshow
is
begin
raise notice 'package private procedure';
end;
end;
/
-- 不能在包外调用私有元素
postgres@postgres=# call pkgtb.privshow;
ERROR: package private procedure ("pkgtb.privshow") is not accessible
LINE 1: call pkgtb.privshow;
创建包体需要注意下面几项:
最后,还有一个细节,就是包的构造函数,如果没有声明构造函数,则会默认添加如下为构造函数。
begin
null;
end;
也可以用户自己定义构造函数:
create or replace package changan -- CREATE PACKAGE 创建包规范
is
procedure shenlan; -- 声明一个存储过程
end;
/
create or replace package body changan -- CREATE PACKAGE BODY 创建包体
is
procedure shenlan
is
begin
raise notice 'hello changan shenlan sl03';
end;
end;
-- 构造函数
begin
raise notice 'package constructor function.';
end;
end;
/
包的调用很简单,与存储过程/函数的调用类似。这里不再细述,可参考LightDB中的存储过程(七)。
create or replace package changan -- CREATE PACKAGE 创建包规范
is
procedure shenlan; -- 声明一个存储过程
end;
/
create or replace package body changan -- CREATE PACKAGE BODY 创建包体
is
procedure shenlan
is
begin
raise notice 'hello changan shenlan sl03';
end;
end;
end;
/
--包的调用
postgres@postgres=# call changan.shenlan;
NOTICE: hello changan shenlan sl03
CALL
这里需要注意:在包规范中声明的任何元素都是公有的,在包外部可见,可通过package-name.element的形式进行调用,在包体中可以直接通过元素名调用。但是,在包体中定义而没有在包规范中声明的元素是私有的,包外无法访问,只能包内调用。
更多请参考LightDB官网