前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Postgresql中的变长参数类型VARIADIC实例与限制

Postgresql中的变长参数类型VARIADIC实例与限制

作者头像
mingjie
发布于 2022-09-30 00:48:26
发布于 2022-09-30 00:48:26
1.4K00
代码可运行
举报
运行总次数:0
代码可运行

Postgresql支持变长参数传递,参数被自动转换为数据传入函数体中,类似C语言的可变参数:int sum(int num_args, ...)

0 定义与执行限制

参数列表中

定义

执行

定义多个VARIADIC

失败,参数列表只能有一个VARIADIC

普通参数+VARIADIC

成功

成功

VARIADIC+普通参数

失败

普通参数带默认+VARIADIC

成功

普通参数带默认+普通参数+VARIADIC

失败(参数列表限制,与VARIADIC无关)

调用时VARIADIC接收到0个参数

失败,VARIADIC至少拿到一个参数,transform阶段报错

调用时使用定向传参

失败,VARIADIC不支持定向传参

调用时有重名函数

优先走非VARIADIC函数,除非参数列表中有显示VARIADIC关键字,或参数数目只能被VARIADIC匹配

1 VARIADIC实例

VARIADIC类型将入参转为数组使用,数据下标从一开始

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test1(VARIADIC arr int[])
LANGUAGE plpgsql
AS $$
DECLARE
    i int;
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
END;
$$;

call var_test1(2,34,55,66);
call var_test1(VARIADIC ARRAY[2,34,55,66]);
call var_test1(VARIADIC arr := ARRAY[2,34,55,66]);

执行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
postgres=*# 
call var_test1(2,34,55postgres=*# call var_test1(2,34,55,66);
NOTICE:  ndims: 1
NOTICE:  len: 4
NOTICE:  lower bound: 1
NOTICE:  2
NOTICE:  34
NOTICE:  55
NOTICE:  66
CALL
postgres=*# call var_test1(VARIADIC ARRAY[2,34,55,66]);
NOTICE:  ndims: 1
NOTICE:  len: 4
NOTICE:  lower bound: 1
NOTICE:  2
NOTICE:  34
NOTICE:  55
NOTICE:  66
CALL
postgres=*# call var_test1(VARIADIC arr := ARRAY[2,34,55,66]);
NOTICE:  ndims: 1
NOTICE:  len: 4
NOTICE:  lower bound: 1
NOTICE:  2
NOTICE:  34
NOTICE:  55
NOTICE:  66
CALL

游标(from digoal)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE FUNCTION var_test2(variadic refcursor[]) RETURNS SETOF refcursor AS $$  
declare  
  res refcursor;  
begin  
 for x in 1..array_length($1,1) loop  
   res := $1[x];  
   open res for select relname from pg_class;  
   return next res;  
 end loop;  
end;  
$$ lANGUAGE plpgsql; 

begin;
select * from var_test2('a','b');  
fetch 1 in a;
commit;

结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
postgres=# begin;
BEGIN
postgres=*# select * from var_test2('a','b');  
 var_test2 
-----------
 a
 b
(2 rows)

postgres=*# fetch 1 in a;
 relname 
---------
 f2
(1 row)

2 定义方式限制(黑盒探索)

定义多个VARIADIC(失败)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test1(VARIADIC arr int[], VARIADIC arr1 int[])
LANGUAGE plpgsql
AS $$
DECLARE
    i int;
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
END;
$$;


ERROR:  VARIADIC parameter must be the last input parameter

VARIADIC前面放普通参数(成功)普通参数匹配后剩下的给VARIADIC

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test1(t1 int, VARIADIC arr int[])
LANGUAGE plpgsql
AS $$
DECLARE
    i int;
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
END;
$$;
call var_test1(2,34,55,66);

VARIADIC后面放普通参数(失败)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test2(VARIADIC arr int[], t1 int)
LANGUAGE plpgsql
AS $$
DECLARE
    i int;
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
END;
$$;
ERROR:  VARIADIC parameter must be the last input parameter

VARIADIC前面放默认值普通参数、无默认参数(失败)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test5(t1 int default 10, t2 int, VARIADIC arr int[])
LANGUAGE plpgsql
AS $$
DECLARE
    i int;
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
    raise notice 't1: %', t1;
END;
$$;
call var_test5(1,2,3);

ERROR:  input parameters after one with a default value must also have defaults

3 调用方式限制

VARIADIC必须接收至少一个参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test3(VARIADIC arr int[])
LANGUAGE plpgsql
AS $$
DECLARE
    i int;
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
END;
$$;
call var_test3();

ERROR:  procedure var_test3() does not exist

定向传参无法用到VARIADIC

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test4(q int default 199, VARIADIC arr int[])
LANGUAGE plpgsql
AS $$
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
    raise notice 'q: %', q;
END;
$$;
-- call var_test4(1, VARIADIC arr := ARRAY[2,34,55,66]);
-- call var_test4(1,2,34,55,66);
-- call var_test4(1, VARIADIC ARRAY[2,34,55,66]);

call var_test4(arr => VARIADIC ARRAY[2,34,55,66]);
ERROR:  procedure var_test4(arr => integer[]) does not exist

call var_test4(1, arr => ARRAY[2,34,55,66]);
ERROR:  procedure var_test4(integer, arr => integer[]) does not exist

同名函数存在,优先使用非VARIADIC函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE or replace PROCEDURE var_test5(VARIADIC arr int[])
LANGUAGE plpgsql
AS $$
BEGIN
    raise notice 'ndims: %', array_ndims(arr);
    raise notice 'len: %', array_length(arr, 1);
    raise notice 'lower bound: %', array_lower(arr, 1);
    for i in 1..array_length(arr,1) loop
      raise notice '%', arr[i];
    end loop;
END;
$$;

CREATE or replace PROCEDURE var_test5(x int)
LANGUAGE plpgsql
AS $$
BEGIN
    raise notice 'x: %', x;
END;
$$;

call var_test5(2);
call var_test5(2,34,55,66);
call var_test5(VARIADIC array[2]);



-- 结果
ss1=# call var_test5(2);
NOTICE:  x: 2
CALL

ss1=# call var_test5(2,34,55,66);
NOTICE:  ndims: 1
NOTICE:  len: 4
NOTICE:  lower bound: 1
NOTICE:  2
NOTICE:  34
NOTICE:  55
NOTICE:  66
CALL

ss1=# call var_test5(VARIADIC array[2]);
NOTICE:  ndims: 1
NOTICE:  len: 1
NOTICE:  lower bound: 1
NOTICE:  2
CALL
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Postgresql中plpgsql事务管理实例(commit/rollback)
对于事务系统来说,内层函数、外层函数都在一个事务中,内层提交就等于把事务提交了,所以外层数据也在。
mingjie
2022/09/30
2.2K0
Postgresql源码(77)plpgsql中参数传递和赋值
总结:函数入参赋值是遍历datums中需要值的变量,然后按顺序拿fcinfo->args数组的值。
mingjie
2022/09/26
7980
Postgresql源码(77)plpgsql中参数传递和赋值
进阶数据库系列(十一):PostgreSQL 存储过程
工作中可能会存在业务比较复杂,重复性工作比较多,需要批量处理数据的情况,此时使用存储过程会方便很多,存储过程的执行效率也会快很多,能帮助我们节省很多代码和时间。
民工哥
2023/08/22
4.3K0
进阶数据库系列(十一):PostgreSQL 存储过程
Postgresql RECORD与%ROWTYPE类型
Postgresql中支持两种行类型,两种类型使用上有一些区别,本篇结合实例简单介绍。
mingjie
2022/10/31
1.1K0
Postgresql源码(79)plpgsql中多层调用时参数传递关键点分析(pl参数)
问题一:外层ExecuteCallStmt用什么构造参数列表fcinfo->args? 问题二:外层ExecuteCallStmt如何fcinfo->args构造流程? 问题三:内层ExecuteCallStmt用什么构造fcinfo->args? 问题四:内层ExecuteCallStmt如何fcinfo->args构造流程? 问题五:exec_stmt_block刚进入初始化哪些变量? 问题六:exec_stmt_block刚进入为什么要初始化哪些变量直接用不行吗? 问题七:内层函数执行完的变量是在哪赋给外层的?
mingjie
2022/09/26
1.3K0
Postgresql源码(87)数组构造与计算(Flat格式与Expand格式)
一句话总结 数组的标准构造函数会生成紧凑的flat结构ArrayType,像元组一样数据跟在后面;pl中会把flat紧凑结构解析到expand数组结构中,并加上mxct内存上下文归属关系,便于计算。
mingjie
2022/10/31
3330
Postgresql源码(87)数组构造与计算(Flat格式与Expand格式)
Postgresql快照堆栈ActiveSnapshot
因为在事务中,有些行为是需要看到最新数据的,比如一个RR事务拿到一个快照后执行了一段时间,这时运行了一条CALL Func或触发器语句,开始进入函数的执行逻辑。
mingjie
2023/04/08
1.1K1
Postgresql快照堆栈ActiveSnapshot
【速记】Postgresql游标短暂的一生
curs4的在exec_stmt_open中被创建出来,创建时使用CreatePortal返回一个游标Portal:
mingjie
2023/04/18
3910
postgresql 触发器 简介(转)
– 把before for each row的触发器删掉, 再测试插入 : postgres=# drop trigger tg02 on t_ret; DROP TRIGGER postgres=# drop trigger tg2 on t_ret; DROP TRIGGER postgres=# insert into t_ret values(1,’digoal’,now()); NOTICE: 00000: tg01 LOCATION: exec_stmt_raise, pl_exec.c:2840 NOTICE: 00000: tg1 LOCATION: exec_stmt_raise, pl_exec.c:2840 NOTICE: 00000: tg03, after for each row 的触发器函数返回空, 不影响后续的触发器是否被调用. 因为只要表上面发生了真正的行操作, after for each row就会被触发, 除非when条件不满足. (这个后面会讲到) LOCATION: exec_stmt_raise, pl_exec.c:2840 NOTICE: 00000: tg3 LOCATION: exec_stmt_raise, pl_exec.c:2840 NOTICE: 00000: tg04 LOCATION: exec_stmt_raise, pl_exec.c:2840 NOTICE: 00000: tg4 LOCATION: exec_stmt_raise, pl_exec.c:2840 INSERT 0 1 – 有数据插入. 这也说明了before for each statement的返回值为空并不会影响数据库对行的操作. 只有before for each row的返回值会影响数据库对行的操作. postgres=# select * from t_ret ; id | info | crt_time —-+——–+—————————- 1 | digoal | 2013-03-10 16:50:39.551481 (1 row)
qubianzhong
2019/07/01
4K0
Postgreqsql动态加载plpgsql钩子函数的实例(调试利器)
Postgresql的plpgsql提供了一套钩子函数支持运行时动态加载,非常便于调试plpgsql。本文总结使用方法和实例。
mingjie
2023/04/18
4270
HAWQ中的行列转置
该文介绍了如何在PostgreSQL中实现交叉表查询,包括定义表、定义列、创建索引、查询结果集合并以及应用函数处理结果集等步骤。同时介绍了如何使用PL/SQL和SQL进行交叉表查询,以及如何使用PostGIS进行空间数据查询和处理。
用户1148526
2018/01/03
1.7K0
Postgresql源码(37)plpgsql函数编译执行流程分析
1、编译过程主要是pl_gram.y做语法匹配的过程plpgsql_yyparse,整体匹配后的结果会作为PLpgSQL_stmt_block结构记录在plpgsql_parse_result中。
mingjie
2022/05/12
1.3K0
Postgresql源码(126)TupleStore使用场景与原理分析
调用SPI_execute_plan_extended执行后,可以看到tstore中有了两条结果。
mingjie
2024/04/18
2140
Postgresql源码(126)TupleStore使用场景与原理分析
Postgresql源码(78)plpgsql中调用call proc()时的参数传递和赋值(pl参数)
《Postgresql源码(77)plpgsql中参数传递和赋值(pl参数)》 《Postgresql源码(78)plpgsql中调用call proc()时的参数传递和赋值(pl参数)》 总结 调用者在exec_stmt_call中拼接ParamListInfo传给SPI去执行call xxxx命令。 ParamListInfo记录了PL的一些回调函数,在SPI会走到:ExecuteCallStmt ExecuteCallStmt核心流程两步: 拼参数列表:会拿到所有入参 假设第一个入参是
mingjie
2022/09/26
1.1K0
Postgresql源码(78)plpgsql中调用call proc()时的参数传递和赋值(pl参数)
Postgresql中procedure支持事务语法(实例&分析)
参考实例1的分析结果,commit执行完了会新起一个事务,后面的保存不影响前面已经提交的事务了。
mingjie
2022/07/14
6690
--PostgreSQL 的存储过程怎么写 与 质疑
PostgreSQL 的存储过程在POSTGRESQL 11 有了改变,从统一的 create function 到 create procedure 到底能从中获得什么
AustinDatabases
2019/10/29
3.9K0
Postgresql中plpgsql异常处理方法与实例(RAISE EXCEPTION)
Postgresql中有关plpgsql异常处理的一切(RAISE EXCEPTION)
mingjie
2022/09/26
4.5K0
Postgresql源码(93)Postgresql函数内事务控制实现原理(附带Oracle对比)
Postgresql与Oracle都是扁平化处理函数内外的事务控制语句的:即函数内的commit也会直接把函数外面的语句提交掉,函数外面的commit也会把之前函数内部的语句提交掉。
mingjie
2022/12/15
1.1K0
Postgresql源码(93)Postgresql函数内事务控制实现原理(附带Oracle对比)
PostgreSQL-模糊查询
函数已改进,请使用新版本函数,参看PostgreSQL 黑科技-递规二分法切分汉字
全栈程序员站长
2022/08/24
2.5K0
Java中获取Postgresql错误码(getErrorCode/getSQLState)
下面表格中列举了一些异常场景,无论执行哪种JAVA中都会抛出SQLException,在异常处理中可以通过三种接口拿到错误信息:
mingjie
2023/05/09
6210
推荐阅读
相关推荐
Postgresql中plpgsql事务管理实例(commit/rollback)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验