Oracle PL/SQL是非常强大的一门SQL编程语言,许多Oracle用户也使用它来处理一些要求延迟低且数据一致性或可靠性要求很高的业务逻辑。
PostgreSQL也有一门非常高级的内置SQL编程语言,plpgsql。与Oracle PL/SQL语法极其类似,但是还是有一些不一样的地方。
(PS:除了plpgsql,PostgreSQL还支持C,java,python,perl等流行的语言作为数据库的函数编程语言)
本文是针对有Oracle用户遇到的一些函数语法与PostgreSQL不兼容的地方,给出的修改建议。
涉及type xx is table of xxxx index by binary_integer语法、type xx is record语法。
CREATE OR REPLACE FUNCTION f_xml(p_xml CLOB) RETURN INT
AS
...
type rec_tk is record
(
tkno VARCHAR2(100) ,
cg_zdj number(12,0) := 0 ,
cg_jsf number(12,0) := 0
);
type tklist is table of rec_tk index by binary_integer;
type rec_cjr is record
(
cjrid varchar2(30) ,
tk tklist
);
type cjr is table of rec_cjr index by binary_integer;
p_cjrs cjr;
FOR j IN 0..v_nllen-1 LOOP
BEGIN
...
p_cjrs(j).cjrid := v_nodevalue;
...
p_cjrs(j).tk(v_tkcount).tkno := v_nodevalue;
p_cjrs(j).tk(v_tkcount).cg_zdj := nvl(v_nodevalue,0);
p_cjrs(j).tk(v_tkcount).cg_jsf := nvl(v_nodevalue,0);
...
v_tkcount:=v_tkcount+1;
END LOOP;
在这个例子中,用到了Oracle在PL/SQL中支持的type定义,以及type table 的定义,这个在PostgreSQL中用法不太一样。
PostgreSQL的type定义需要在数据库中定义,而不是函数中定义。
以上PL/SQL函数在plpgsql中需要作出如下调整:
.1.
type rec_tk is record
(
tkno VARCHAR2(100) ,
cg_zdj number(12,0) := 0 ,
cg_jsf number(12,0) := 0
);
type tklist is table of rec_tk index by binary_integer;
修改为
函数外执行创建类型的SQL
create type rec_tk as
(
tkno VARCHAR(100) ,
cg_zdj numeric(12,0) ,
cg_jsf numeric(12,0)
);
.2.
type rec_cjr is record
(
cjrid varchar2(30) ,
tk tklist
);
type cjr is table of rec_cjr index by binary_integer;
p_cjrs cjr;
修改为
函数外执行创建类型的SQL
create type rec_cjr as
(
cjrid varchar(30) ,
tk rec_tk[]
);
函数内对table的使用修改为数组的使用,数组的下标从1开始。
p_cjrs rec_cjr[];
.3.
p_cjrs(j).cjrid := v_nodevalue;
...
p_cjrs(j).tk(v_tkcount).tkno := v_nodevalue;
p_cjrs(j).tk(v_tkcount).cg_zdj := nvl(v_nodevalue,0);
p_cjrs(j).tk(v_tkcount).cg_jsf := nvl(v_nodevalue,0);
plpgsql目前不能直接修改复合数组对应的composite.element
需要修改为
declare
v_p_cjrs rec_cjr;
v_tk rec_tk;
...
v_p_cjrs.cjrid := v_nodevalue;
p_cjrs[j] := v_p_cjrs.cjrid;
...
v_tk.tkno := v_nodevalue;
v_tk.cg_zdj := nvl(v_nodevalue,0);
v_tk.cg_jsf := nvl(v_nodevalue,0);
v_p_cjrs.tk[v_tkcount] := v_tk;
p_cjrs[j] := v_p_cjrs;
或者请参考如下例子
do language plpgsql
$$
declare
vtk rec_tk;
vtk_a rec_tk[];
vcjr rec_cjr;
vcjr_a rec_cjr[];
begin
vtk := row('a', 1,2);
-- or vtk.tkno := 'a'; vtk.cg_zdj := 1; vtk.cg_jsf := 2;
vtk_a[1] := vtk;
vcjr := row('test', vtk_a);
-- or vcjr := row('test', array[row('a',1,2)]);
-- or vcjr.cjrid := 'test'; vcjr.tk := vtk_a;
-- or vcjr_a[1] := row('test', array[row('a',1,2)]);
vcjr_a[1] := vcjr;
raise notice 'vtk %, vtk_a % vcjr % vcjr_a % ', vtk, vtk_a, vcjr, vcjr_a;
end;
$$
;
NOTICE: 00000: vtk (a,1,2), vtk_a {"(a,1,2)"} vcjr (test,"{""(a,1,2)""}") vcjr_a {"(test,\"{\"\"(a,1,2)\"\"}\")"}
LOCATION: exec_stmt_raise, pl_exec.c:3216
DO
nvl函数参考PostgreSQL Oracle兼容包orafce。
.4.
array用法简介
http://blog.163.com/digoal@126/blog/static/163877040201201275922529/
https://www.postgresql.org/docs/9.5/static/arrays.html
https://www.postgresql.org/docs/9.5/static/plpgsql-control-structures.html#PLPGSQL-FOREACH-ARRAY
循环
[ <
行列转换
https://www.postgresql.org/docs/9.5/static/functions-array.html
unnest(ARRAY[1,2])
1
2