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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 背景 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数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
8天前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
|
8天前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
13天前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
|
4月前
|
SQL 关系型数据库 MySQL
Go语言数据库编程:使用 `database/sql` 与 MySQL/PostgreSQL
Go语言通过`database/sql`标准库提供统一数据库操作接口,支持MySQL、PostgreSQL等多种数据库。本文介绍了驱动安装、连接数据库、基本增删改查操作、预处理语句、事务处理及错误管理等内容,涵盖实际开发中常用的技巧与注意事项,适合快速掌握Go语言数据库编程基础。
286 62
|
4月前
|
SQL 关系型数据库 PostgreSQL
CTE vs 子查询:深入拆解PostgreSQL复杂SQL的隐藏性能差异
本文深入探讨了PostgreSQL中CTE(公共表表达式)与子查询的选择对SQL性能的影响。通过分析两者底层机制,揭示CTE的物化特性及子查询的优化融合优势,并结合多场景案例对比执行效率。最终给出决策指南,帮助开发者根据数据量、引用次数和复杂度选择最优方案,同时提供高级优化技巧和版本演进建议,助力SQL性能调优。
326 1
|
5月前
|
Oracle 关系型数据库 数据库
【赵渝强老师】在PostgreSQL中访问Oracle
本文介绍了如何在PostgreSQL中使用oracle_fdw扩展访问Oracle数据库数据。首先需从Oracle官网下载三个Instance Client安装包并解压,设置Oracle环境变量。接着从GitHub下载oracle_fdw扩展,配置pg_config环境变量后编译安装。之后启动PostgreSQL服务器,在数据库中创建oracle_fdw扩展及外部数据库服务,建立用户映射。最后通过创建外部表实现对Oracle数据的访问。文末附有具体操作步骤与示例代码。
167 6
【赵渝强老师】在PostgreSQL中访问Oracle
|
7月前
|
SQL Oracle 关系型数据库
|
SQL Cloud Native 关系型数据库
ADBPG(AnalyticDB for PostgreSQL)是阿里云提供的一种云原生的大数据分析型数据库
ADBPG(AnalyticDB for PostgreSQL)是阿里云提供的一种云原生的大数据分析型数据库
1775 1
|
数据可视化 关系型数据库 MySQL
将 PostgreSQL 迁移到 MySQL 数据库
将 PostgreSQL 迁移到 MySQL 数据库
2287 2
|
SQL 存储 自然语言处理
玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
在当今社交媒体的时代,人们通过各种平台分享自己的生活、观点和情感。然而,对于平台管理员和品牌经营者来说,了解用户的情感和意见变得至关重要。为了帮助他们更好地了解用户的情感倾向,我们可以使用PostgreSQL中的pg_jieba插件对这些发帖进行分词和情感分析,来构建一个社交媒体情感分析系统,系统将根据用户的发帖内容,自动判断其情感倾向是积极、消极还是中性,并将结果存储在数据库中。
玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词

相关产品

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

    更多