PostgreSQL Oracle 兼容性 之 - PL/SQL record, table类型定义

简介: 背景 Oracle PL/SQL是非常强大的一门SQL编程语言,许多Oracle用户也使用它来处理一些要求延迟低且数据一致性或可靠性要求很高的业务逻辑。 PostgreSQL也有一门非常高级的内置SQL编程语言,plpgsql。与Oracle PL/SQL语法极其类似,但是还是有一些不一样的

背景

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语法。

Oracle PL/SQL 例子

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 PL/SQL 兼容性例子

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

循环

[ <<label>> ]
FOREACH target [ SLICE number ] IN ARRAY expression LOOP
    statements
END LOOP [ label ];

行列转换
https://www.postgresql.org/docs/9.5/static/functions-array.html

    unnest(ARRAY[1,2])
1
2

小结

  1. 使用composite type替代了PL/SQL的type定义。
  2. 使用array替代了PL/SQL的table定义。
  3. 复合类型的数组,不能直接修改复合类型的element,需要先用标量修改好后赋值。

RDS PG内核改进建议

  1. 新增 CREATE TYPE [ IF NOT EXISTS ] 语法。这样的话用户就不需要将这个语法写在函数外了,可以在函数内直接执行。
  2. PL/SQL的type是局部变量,而PostgreSQL的type是全局的,这个也需要注意,如果多个PL/SQL函数用到了同样的type name但是结构不一样,port到plpgsql时,需要创建多个type,在plpgsql中分别使用对应的type name。
  3. plpgsql 暂时不支持composite数组直接设置element的值,需要加强plpgsql的语法功能。
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
11月前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
671 8
|
Oracle 关系型数据库 数据库
【赵渝强老师】在PostgreSQL中访问Oracle
本文介绍了如何在PostgreSQL中使用oracle_fdw扩展访问Oracle数据库数据。首先需从Oracle官网下载三个Instance Client安装包并解压,设置Oracle环境变量。接着从GitHub下载oracle_fdw扩展,配置pg_config环境变量后编译安装。之后启动PostgreSQL服务器,在数据库中创建oracle_fdw扩展及外部数据库服务,建立用户映射。最后通过创建外部表实现对Oracle数据的访问。文末附有具体操作步骤与示例代码。
1423 6
【赵渝强老师】在PostgreSQL中访问Oracle
|
SQL Oracle 关系型数据库
解决大小写、保留字与特殊字符问题!Oracle双引号在SQL中的特殊应用
在Oracle数据库开发中,双引号的使用是一个重要但易被忽视的细节。本文全面解析了双引号在SQL中的特殊应用场景,包括解决标识符与保留字冲突、强制保留大小写、支持特殊字符和数字开头标识符等。同时提供了最佳实践建议,帮助开发者规避常见错误,提高代码可维护性和效率。
712 6
|
SQL Oracle 关系型数据库
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
|
SQL Oracle 关系型数据库
【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差
【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差
|
SQL Oracle 关系型数据库
如何在 Oracle 中配置和使用 SQL Profiles 来优化查询性能?
在 Oracle 数据库中,SQL Profiles 是优化查询性能的工具,通过提供额外统计信息帮助生成更有效的执行计划。配置和使用步骤包括:1. 启用自动 SQL 调优;2. 手动创建 SQL Profile,涉及收集、执行调优任务、查看报告及应用建议;3. 验证效果;4. 使用 `DBA_SQL_PROFILES` 视图管理 Profile。
|
SQL Oracle 关系型数据库
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
本文来自YashanDB官网,介绍如何处理Oracle客户端sql*plus中使用@@调用同级目录SQL脚本的场景。崖山数据库23.2.x.100已支持@@用法,但旧版本可通过Python脚本批量重写SQL文件,将@@替换为绝对路径。文章通过Oracle示例展示了具体用法,并提供Python脚本实现自动化处理,最后调整批处理脚本以适配YashanDB运行环境。
|
SQL 关系型数据库 Oracle
ORACLE SQL优化之ORA-03150&ORA-02055&ORA-02063
                                                                                                             >   
5186 0
|
SQL Oracle 关系型数据库
Oracle SQL优化之多表连接
Oracle SQL优化之多表连接
927 0
Oracle SQL优化之多表连接
|
SQL 存储 Oracle
Oracle数据库 | SQL语句执行计划、语句跟踪与优化实例
Oracle数据库 | SQL语句执行计划、语句跟踪与优化实例
610 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多