兼容Oracle的CALL INTO
2. 功能说明
-
CALL支持调用单独的或定义在包中函数和存储过程。
-
CALL调用函数时,增加INTO子句语法,插入的目标是一个host variable。
-
CALL调用无参或全取默认值的函数/存储过程不能省略空括号。
-
CALL在调用函数和存储过程时的参数或INTO子句中支持引用绑定变量。
-
CALL语句中OUT参数对应的绑定变量支持对精度和数据类型的验证。
-
输出绑定变量不允许被重复绑定。
3. 测试用例
3.1. call into调用函数,并插入host variable
-- 创建函数
ivorysql=# create or replace function f_defs(a number default 1314)
ivorysql-# return number
ivorysql-# is
ivorysql-# begin
ivorysql-# raise notice '%', a;
ivorysql-# return a;
ivorysql-# end;
ivorysql-# /
CREATE FUNCTION
-- 声明绑定变量
ivorysql=# variable x number
-- 调用函数并获取返回值
ivorysql=# call f_defs() into :x;
NOTICE: 1314
Call completed.
ivorysql=# print x
X
------
1314
3.2. call调用包中的存储过程
ivorysql=# create table tb1(c1 int);
CREATE TABLE
-- 创建包规范
ivorysql=# create or replace package pkg is
ivorysql-# var1 integer;
ivorysql-# procedure test_p ;
ivorysql-# end;
ivorysql-# /
CREATE PACKAGE
-- 创建包体
ivorysql=# create or replace package body pkg is
ivorysql-# procedure test_p is
ivorysql-# begin
ivorysql-# insert into tb1 values(1);
ivorysql-# end;
ivorysql-# begin
ivorysql-# var1 := 2;
ivorysql-# end;
ivorysql-# /
CREATE PACKAGE BODY
-- 调用包中的过程
ivorysql=# call pkg.test_p();
CALL
ivorysql=# select * from tb1;
c1
-----
1
(1 row)
3.3. 无参和默认参数调用
-- 创建带默认参数函数
ivorysql=# CREATE OR REPLACE FUNCTION default_arg_func(p_num NUMBER DEFAULT 100) RETURN NUMBER AS
ivorysql-# BEGIN
ivorysql-# RETURN p_num + 5;
ivorysql-# END;
ivorysql-# /
CREATE FUNCTION
-- 正确调用默认参数函数(必须带括号)
ivorysql=# VARIABLE default_result NUMBER;
ivorysql=# CALL default_arg_func() INTO :default_result; -- 使用默认值100
Call completed.
ivorysql=# PRINT default_result;
DEFAULT_RESULT
----------------
105
-- 带参数调用
ivorysql=# CALL default_arg_func(200) INTO :default_result;
Call completed.
ivorysql=# PRINT default_result;
DEFAULT_RESULT
----------------
205
3.4. 在参数或INTO子句中引用绑定变量
-- 设置输入绑定变量
ivorysql=# VARIABLE input_num NUMBER = 7;
-- 使用绑定变量作为参数调用函数
ivorysql=# VARIABLE func_result NUMBER;
ivorysql=# CALL stand_alone_func(:input_num) INTO :func_result;
Call completed.
ivorysql=# PRINT func_result;
FUNC_RESULT
-------------
14
3.5. CALL语句中OUT参数支持精度和数据类型验证
-- 创建带OUT参数的过程
ivorysql=# CREATE OR REPLACE PROCEDURE out_param_proc(
ivorysql(# p_in IN VARCHAR2,
ivorysql(# p_out OUT VARCHAR2,
ivorysql(# p_num_out OUT NUMBER
ivorysql(# ) AS
ivorysql-# BEGIN
ivorysql-# p_out := p_in || ' processed';
ivorysql-# p_num_out := LENGTH(p_in);
ivorysql-# END;
ivorysql-# /
CREATE PROCEDURE
-- 测试OUT参数类型匹配
ivorysql=# VARIABLE out_var VARCHAR2(50);
ivorysql=# VARIABLE num_var NUMBER;
ivorysql=# CALL out_param_proc('Test input', :out_var, :num_var);
Call completed.
ivorysql=# PRINT out_var;
OUT_VAR
----------------------
Test input processed
ivorysql=# PRINT num_var;
NUM_VAR
---------
10
-- 测试OUT参数精度不足(会截断)
ivorysql=# VARIABLE short_out VARCHAR2(5);
ivorysql=# CALL out_param_proc('Long input string', :short_out, :num_var);
Call completed.
ivorysql=# PRINT short_out;
SHORT_OUT
-----------
Long
-- 测试类型不匹配(会报错)
ivorysql=# VARIABLE wrong_type NUMBER;
ivorysql=# CALL out_param_proc('Test', :wrong_type, :num_var);
ERROR: invalid input syntax for type numeric: "Test processed"
3.6. 输出绑定变量不允许重复绑定
-- 准备绑定变量
ivorysql=# VARIABLE dup_var VARCHAR2(100);
-- 尝试重复绑定(会报错)
ivorysql=# CALL out_param_func('Test', :dup_var) INTO :dup_var;
ERROR: output parameter cannot be a duplicate bind
-- 正确做法:使用不同的绑定变量
ivorysql=# VARIABLE out1 VARCHAR2(100);
ivorysql=# CALL out_param_proc('Correct usage', :out1, :num_var);
Call completed.
ivorysql=# PRINT out1;
OUT1
-------------------------
Correct usage processed