KingbaseES 为了更好地适应用户的oracle 应用,实现了对 plsql 的支持,用户可以根据需要使用 plsql 或 plpgsql。 以下简要介绍下二者的差异

一、格式差异

1、plpgsql

plpgsql 必须有 label

[ <<label>> ]
[ DECLARE declarations ]
BEGIN
statements
END [ label ];

具体例子:

create or replace function pgsql_test(part integer)
returns integer as $$
declare
v_total integer;
begin
if part = 0 then
select count(*) into v_total from t0;
else
select count(*) into v_total from t1;
end if;
return v_total;
end;
$$ language plpgsql;

2、plsql

plsql 不需要有 label

create or replace function plsql_func01(part integer)
returns integer as
declare
v_total integer;
begin
if part = 0 then
select count(*) into v_total from t0;
else
select count(*) into v_total from t1;
end if;
return v_total;
end;

如果后面没有指明language,KingbaseES 视database_mode参数决定采用哪种解析器。如果database_mode=oracle,默认采用的是plsql 解析器;如果database_mode=pg,则默认采用plpgsql解析器。

二、plsql 支持存储过程

PG11之前,对于plpgsql,函数实际上也称作存储过程,也就是实际没有 create procedure 的概念,函数可以完成数据库的DML操作,实际 function 和 procedure 功能上没有区别。

KingbaseES plsql 同时支持 function and procedure,与oracle function不同,KingbaseES function内部可以进行DML操作。

procedure:过程调用 call plsql_proc01();

create or replace procedure plsql_proc01
as
begin
insert into t0 values(1);
end;

function:函数调用 select plsql_func01();

create or replace function plsql_func01
return integer as
begin
insert into t0 values(1);
return 1;
end;

注:oracle plsql,function 必须作为表达式一部分进行调用,函数体内如果有 DML操作,在调用时是会报错,函数含有自治事务的除外。

三、是否支持嵌套事务

1、plpgsql

plpgsql 并不支持嵌套事务,函数中的事务总是由外层命令(函数的调用者)来控制的,它们本身无法开始或提交事务。

pgisdb=> create or replace function plsql_test(part integer)
pgisdb-> returns integer as
pgisdb-> declare
pgisdb-> v_total integer;
pgisdb-> begin
pgisdb-> if part = 0 then
pgisdb-> select count(*) into v_total from t0;
pgisdb-> commit;
pgisdb-> else
pgisdb-> select count(*) into v_total from t1;
pgisdb-> end if;
pgisdb-> return v_total;
pgisdb-> end;
pgisdb-> /
CREATE FUNCTION

pgisdb=> select plsql_test(0);
ERROR: invalid transaction termination
CONTEXT: PL/SQL function plsql_test(integer) line 7 at COMMIT

2、plsql

对于function,不支持函数体内 commit ,事务是否提交由外层事务决定。在V8R6C5版本,将支持函数commit。

pgisdb=> create or replace function plsql_func01
pgisdb-> return integer as
pgisdb-> begin
pgisdb-> insert into t0 values(1);
pgisdb-> commit;
pgisdb-> return 1;
pgisdb-> end;
pgisdb-> /
CREATE FUNCTION

pgisdb=> select plsql_func01();
ERROR: invalid transaction termination
CONTEXT: PL/SQL function plsql_func01() line 4 at COMMIT

对于procedure,内部允许commit or rollback。

pgisdb=> create or replace procedure plsql_proc01
pgisdb-> as
pgisdb-> begin
pgisdb-> insert into t0 values(1);
pgisdb-> commit;
pgisdb-> end;
pgisdb-> /
CREATE PROCEDURE pgisdb=> call plsql_proc01();
CALL

注意:如果过程体内含有commit or rollback,则不能在外层再 begin transaction。

pgisdb=> create or replace procedure plsql_proc01
pgisdb-> as
pgisdb-> begin
pgisdb-> insert into t0 values(1);
pgisdb-> commit;
pgisdb-> end;
pgisdb-> /
CREATE PROCEDURE pgisdb=> begin;
BEGIN
pgisdb=> call plsql_proc01();
ERROR: invalid transaction termination
CONTEXT: PL/SQL function plsql_proc01() line 4 at COMMIT

四、性能比较

create or replace function pgsql_test()
returns integer as $$
declare
v_total integer;
begin
select count(*) into v_total from t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
return v_total;
end;
$$ language plpgsql; test=# begin
test-# for i in 1..100000 loop
test-# perform pgsql_test();
test-# end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 2450.671 ms (00:02.451) ============ create or replace function plsql_test()
returns integer as
declare
v_total integer;
begin
select count(*) into v_total from t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
return v_total;
end;
/ test=# begin
test-# for i in 1..100000 loop
test-# perform plsql_test();
test-# end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 2454.302 ms (00:02.454)

五、其他差异

1、循环变量定义

plsql: 循环变量 i 可以不用提前定义

create or replace procedure plsql_proc() as
begin
for i in select regexp_split_to_table('ab,bc,cd',',') loop
raise notice '%',i;
end loop;
end;

plpgsql: 循环变量必须提取定义

create or replace procedure plpgsql_proc() as
$$
begin
for i in select regexp_split_to_table('ab,bc,cd',',') loop
raise notice '%',i;
end loop;
end;
$$ language plpgsql; ERROR: loop variable of loop over rows must be a record variable or list of scalar variables
LINE 4: for i in select regexp_split_to_table('ab,bc,cd',',') loop create or replace procedure plpgsql_proc() as
$$
declare
v_text text;
begin
for v_text in select regexp_split_to_table('ab,bc,cd',',') loop
raise notice '%',v_text;
end loop;
end;
$$ language plpgsql;

2、execute & execute immediate

plsql 支持 execute or execute immediate , plpgsql 只支持 execute

PLSQL 与 PLPGSQL的更多相关文章

  1. plpgsql insert 性能 测试

    有时需要执行一些sql脚本,带逻辑控制语句,又不想用高级语言C#.Java之类的,可以直接用plpgsql,类似于Oracle的plsql. do language 'plpgsql' $$ decl ...

  2. plpgsql 编译执行

    Oracle 的存储过程或函数提供了两种执行方式: 解释执行:将源代码逐条转换成目标代码,解释一条,执行一条的过程.PLPGSQL将语句翻译成中间形式的系统代码,并在运行时进行解释. 编译执行:将源代 ...

  3. PLSql Oracle配置

    1.安装Oracle客户端或者服务端 2.配置环境变量 <1>.一般如果安装了Oracle客户端或者服务端的话,在环境变种的Path中有Oracle的安装路径(计算机-属性-高级系统设置- ...

  4. plsql查询乱码问题解决

    步骤一:新建变量,设置变量名:NLS_LANG,变量值:SIMPLIFIED CHINESE_CHINA.ZHS16GBK,确定即可: 步骤二: 退出plsql,重新登陆plsql.输入sql语句,执 ...

  5. Oracle/PLSQL: ORA-06550

    参考: http://blog.csdn.net/haiross/article/details/20612135 Oracle/PLSQL: ORA-06550 Learn the cause an ...

  6. [No00008F]PLSQL自动登录,记住用户名密码&日常使用技巧

    配置启动时的登录用户名和密码 这是个有争议的功能,因为记住密码会给带来数据安全的问题. 但假如是开发用的库,密码甚至可以和用户名相同,每次输入密码实在没什么意义,可以考虑让PLSQL Develope ...

  7. 使用plsql创建表空间和用户

    使用plsql创建oracle数据库的表空间和用户,并授权的语句.1.创建表空间:说明:datafile是指定创建位置,指向oracle数据库的默认位置:autoextend 设置容量为自动增长,50 ...

  8. plsql查找不到带中文的纪录

    今天在另外的电脑用plsql查询不到带中文的记录 select * from test where name like '%测试%' 然后发现是系统的环境变量还没设置好所造成的.在系统变量加入如下变量 ...

  9. plsql配置远程连接数据库

    1.先安装plsql.地址:http://pan.baidu.com/s/1hqGbATI 2.  解压缩 instantclient_11_2(这个客户端可以在网上找精简版的),找到以下路径  \i ...

随机推荐

  1. 【python基础】第06回 运算符和流程控制 1

    本章内容概要 1.运算符 2.流程控制 本章内容详解 1.运算符 什么是运算符? 运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算.例如:2+3,其操作数是2和3,而运算符则是" ...

  2. Python控制自己的手机摄像头拍照,并把照片自动发送到邮箱

    写在前面的一些P话: 今天这个案例,就是控制自己的摄像头拍照,并且把拍下来的照片,通过邮件发到自己的邮箱里.想完成今天的这个案例,只要记住一个重点:你需要一个摄像头 思路 通过opencv调用摄像头拍 ...

  3. Redis docker 主从模式与哨兵sentinel

    更多技术记录,请参考软件开发 | 编程 | RustFisher 为实现redis的高可用,我们采用主从模式加哨兵的方法. 一主二从三哨兵,共启动6个redis容器.本文示例在同一个服务器上进行操作. ...

  4. 《Ranked List Loss for Deep Metric Learning》CVPR 2019

    Motivation: 深度度量学习的目标是学习一个嵌入空间来从数据点中捕捉语义信息.现有的成对或者三元组方法随着模型迭代过程会出现大量的平凡组导致收敛缓慢.针对这个问题,一些基于排序结构的损失取得了 ...

  5. STM32液晶显示HT1621驱动原理及程序代码

    1.HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示: 图1 与单片机 ...

  6. SpringBoot数据库管理 - 用flyway对数据库管理和迁移

    上文介绍了Liquibase,以及和SpringBoot的集成.除了Liquibase之外,还有一个组件Flyway也是经常被使用到的类似的数据库版本管理中间件.本文主要介绍Flyway, 以及Spr ...

  7. 创建私有CA,我就用openSSL

    目录 简介 搭建root CA 生成root CA 使用CRL 使用OSCP 总结 简介 一般情况下我们使用的证书都是由第三方权威机构来颁发的,如果我们有一个新的https网站,我们需要申请一个世界范 ...

  8. js基础学习-数组

    let arr1 = [ {name: 1} ] let arr2 = [ {age: 23} ] let ages = [11, 22, 23] let newArr = arr1.concat(a ...

  9. 小A的柱状图_via牛客网

    题目 链接:https://ac.nowcoder.com/acm/contest/28537/Q 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语 ...

  10. Go语言基础五:引用类型-切片和映射

    切片 Go的数组长度不可以改变,在某些特定的场景中就不太适用了.对于这种情况Go语言提供了一种由数组建立的.更加灵活方便且功能强大的包装(Wapper),也就是切片.与数组相比切片的长度不是固定的,可 ...