Kingbase ES函数参数模式与Oracle的异同

发布时间 2023-09-18 14:27:02作者: KINGBASE研究院

文章概要:

本文对主要就KES和Oracle的PLSQL中关于存储过程参数模式异同进行介绍,列举和验证了存在的差异

(如果想直接看差异的结论可直接跳到末尾)。

一,存储过程的三种参数模式

重新回顾一下,PLSQL中存储过程的三种参数模式IN、OUT、INOUT
1,IN参数模式,也是默认的模式,在存储过程运行的时候就应该具有值
2,OUT参数模式,定义的参数只能在存储过程体内部赋值,表示该参数可以将某个值传递到外部调用处。
3,IN OUT简单来说就是存储过程调用处传递的实参,在过程体内会被接收到,并且在存储过程体内为形参赋的值也会被传递到存储过程调用处。

二,IN模式

共同点:
1,IN模式是参数的默认模式,且可以不写IN,
2,应该在程序运行的时候已经具有值
3,可以设置默认值
差异点:
Oracle--》参数不可以在程序体内重新赋值,即只能传入给程序使用
KES-----》参数可以在程序体内重新赋值

对差异点进行验证

--测试用例1:

--存储过程in_proc
 create or replace procedure in_proc (
    p_a in number , 
    p_b number   --默认为IN模式
 )as
 begin
    p_a := 10 ; --实参被传递进来以后,在这个程序体中Oracle不支持修改,KES支持修改
    p_b := 20 ;
    dbms_output.put_line(p_a);
    dbms_output.put_line(p_b);
 end ;
 --测试存储过程
 declare
    va  int;
    vb  int;
 begin
    va := 11;
    vb := 12;
    call in_proc(va,vb);
 end

--oracle编译存储过程直接报错:

Procedure IN_PROC 已编译

LINE/COL  ERROR

--------- -------------------------------------------------------------

6/5       PLS-00363: 表达式 'P_A' 不能用作赋值目标
6/5       PL/SQL: Statement ignored
7/5       PLS-00363: 表达式 'P_B' 不能用作赋值目标
7/5       PL/SQL: Statement ignored
错误: 查看编译器日志

--KES结果,正常输出:

test:=#  declare
test-#     va  int;
test-#     vb  int;
test-#  begin
test-#     va := 11;
test-#     vb := 12;
test-#     call in_proc(va,vb);
test-#  end
test-# /
ANONYMOUS BLOCK
10
20
test:=#

三,OUT模式

共同点:
1,OUT模式必须有OUT关键字,不可以省略
2,只能在程序体内赋值(可以在调用层赋值,但是对程序内外都没有意义,见下例子2)
差异点1:(见下例子3)
Oracle--》OUT和IN OUT参数都不具有默认值。
KES-----》默认情况下OUT和IN OUT参数也都不具有默认值。但是可以开启set comp_v7_program_para_def := on来实现
差异点2:(见下例子4)
Oracle--》必须用实参变量调用
KES-----》非必须用实参变量调用(如果传一个常量也没有意义)

--测试用例2:

--存储过程out_proc
 create or replace procedure out_proc (
    p_a number , 
    p_b OUT number   
 )as
 begin
    p_b := 20 ;
    dbms_output.put_line(p_a);
    dbms_output.put_line(p_b);
 end ;


 --测试存储过程
 declare
    va  int;
    vb  int;
 begin
    va := 11;
    vb := 12;
    out_proc(va,vb);
    dbms_output.put_line(vb);
 end;

oracle结果

11
20
20

PL/SQL 过程已成功完成。

KES运行结果

test:=#  declare
test-#     va  int;
test-#     vb  int;
test-#  begin
test-#     va := 11;
test-#     vb := 12;
test-#     out_proc(va,vb);
test-#     dbms_output.put_line(vb);
test-#  end
test-# /
ANONYMOUS BLOCK
11
20
20
test:=#

效果一致

--测试用例3:

--开启GUC参数
test:=# set comp_v7_program_para_def := on
test-# /
SET

create or replace procedure out_proc01 (
    p_a number , 
    p_b OUT number := 10   
)as
begin
    dbms_output.put_line(p_a);
    p_a := 10 ; --实参被传递进来以后,在这个程序体中Oracle不支持修改,KES支持修改
    dbms_output.put_line(p_a);
    dbms_output.put_line(p_b);
end ;

 --测试存储过程
 declare
    va  int;
    vb  int;
 begin
    va := 11;
    out_proc01(va);
    dbms_output.put_line(vb);
 end

----oracle测试结果(OUT 和 IN OUT 的形参不能有默认值)

Procedure OUT_PROC01 已编译

LINE/COL  ERROR

--------- -------------------------------------------------------------

3/2       PLS-00230: OUT 和 IN OUT 的形参不能有默认表达式
7/2       PL/SQL: Statement ignored
7/2       PLS-00363: 表达式 'P_A' 不能用作赋值目标
错误: 查看编译器日志

----kes测试结果

test:=#  --测试存储过程
test:=#  declare
test-#     va  int;
test-#     vb  int;
test-#  begin
test-#     va := 11;
test-# out_proc01(va);
test-#     dbms_output.put_line(vb);
test-#  end
test-# /
ANONYMOUS BLOCK
11
10
10
      --这里有个NULL值
test:=#

--测试用例4:

--存储过程继续沿用测试用例2中的
--测试存储过程
 declare
    va  int;
    vb  int;
 begin
    va := 11;
    out_proc(va,15);
    dbms_output.put_line(vb);
 end

---oracle运行结果(调用报错,实参不能是常量)

在行: 299 上开始执行命令时出错 -
 declare
    va  int;
    vb  int;
 begin
    va := 11;
    out_proc(va,15);
    dbms_output.put_line(vb);
 end;
 错误报告 -
ORA-06550: 第 6 行, 第 14 列: 
PLS-00363: 表达式 'TO_NUMBER(SQLDEVBIND1Z_1)' 不能用作赋值目标
ORA-06550: 第 6 行, 第 2 列: 
PL/SQL: Statement ignored

6550. 00000 -  "line %s, column %s:\n%s"
      *Cause:    Usually a PL/SQL compilation error.
      *Action:

---KES运行结果

test:=# --测试存储过程
test:=#  declare
test-#     va  int;
test-#     vb  int;
test-#  begin
test-#     va := 11;
test-#     out_proc(va,15);
test-#     dbms_output.put_line(vb);
test-#  end
test-# /
ANONYMOUS BLOCK
11
20
    --为NULL,说明OUT模式传一个常量没有实际意义
test:=#

四,IN OUT模式

IN OUT模式相比于OUT模式,
新增的差异点:
KES:支持INOUT和IN OUT两种写法,而ORACLE只支持IN OUT写法。
其他的异同则和OUT模式一样。

create or replace procedure inout_proc (
    p_a number , 
    p_b INOUT number   --oracle不知此这种写法
)
as
begin
    dbms_output.put_line(p_a);
    dbms_output.put_line(p_b);
    p_b := 20;
end ;


 --测试存储过程
 declare
    va  int;
    vb  int;
 begin
    va := 11;
    vb := 21;
    inout_proc(va,vb);
    dbms_output.put_line(vb);
 end

--KES输出结果

ANONYMOUS BLOCK
11
21
20
test=#

oracle则无法编译通过inout_proc

五,小结

从上面的各节来看,Oracle的语法以及功能限制更为严格和苛刻,而KES的语法形式更为灵活多样,KES在兼容ORACLE的

所有参数模式功能外,还存在着一些差异,一次性罗列差异如下:

1,对于IN模式而言,KES的参数可以在程序体内重新赋值,而ORACLE则不行,即只能传入给程序使用

2,OUT和IN OUT参数ORACLE都不具有默认值,而KES默认也是如此,但是可以通过comp_v7_program_para_def配置为ON
解除该限制

3,OUT模式的形参ORACLE必须要求使用实参变量调用,而KES则不强制,尽管用一个常量实测没什么意义。

4,KES支持INOUT和IN OUT两种写法,而ORACLE只支持IN OUT写法。