You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL 12+:如何将表中列的多行值传递给函数?

问题解决与方案选择

先解决当前错误

你遇到的错误是因为(select ARRAY[dokumnr] from source)返回了两行单元素数组,而函数需要的是一个包含所有值的单一数组。把ARRAY[dokumnr]换成array_agg(dokumnr)就能生成包含所有source列值的数组,修正后的调用语句:

select TestAddAssetTransactions( (select array_agg(dokumnr) from source) )

原函数逻辑无需修改,这样就能正常运行。

三种传递方式的对比与实现

1. 数组方式(你最初的思路)

适合单列简单数据,语法简洁,处理少量数据效率不错。除了上面的修正,函数里的unnest用法可以简化:

-- 简化后的函数
CREATE OR REPLACE FUNCTION public.TestAddAssetTransactions(dokumnrs int[]) 
 RETURNS int AS
$BODY$
with i1 as (
INSERT INTO bilkaib (dokumnr)
select dokumnr from dok where dokumnr = any(dokumnrs) -- 用=any替代unnest子查询
returning *
)
select count(*) from i1;
$BODY$ language sql;

2. 自定义表类型(更适合结构化数据)

如果以后需要传递多列数据,或者想让语义更清晰,推荐用自定义表类型:

-- 先创建表类型
create type int_dok_type as (dokumnr int);

-- 修改函数参数为表类型数组
CREATE OR REPLACE FUNCTION public.TestAddAssetTransactions(dokumnrs int_dok_type[]) 
 RETURNS int AS
$BODY$
with i1 as (
INSERT INTO bilkaib (dokumnr)
select t.dokumnr from dok, unnest(dokumnrs) t where dok.dokumnr = t.dokumnr
returning *
)
select count(*) from i1;
$BODY$ language sql;

-- 调用方式:用array_agg打包行数据
select TestAddAssetTransactions( (select array_agg(row(dokumnr)) from source) )

如果想更直接,还可以把函数参数设为setof int_dok_type(即行集合),调用时直接传入子查询:

CREATE OR REPLACE FUNCTION public.TestAddAssetTransactions(dokumnrs setof int_dok_type) 
 RETURNS int AS
$BODY$
with i1 as (
INSERT INTO bilkaib (dokumnr)
select t.dokumnr from dok, dokumnrs t where dok.dokumnr = t.dokumnr
returning *
)
select count(*) from i1;
$BODY$ language sql;

-- 调用更简洁
select TestAddAssetTransactions(select row(dokumnr) from source);

3. 临时表方式(适合超大量数据)

如果要处理的数据量极大,临时表是个选择,但函数会依赖临时表的存在,耦合性较高:

-- 函数直接读取临时表
CREATE OR REPLACE FUNCTION public.TestAddAssetTransactions() 
 RETURNS int AS
$BODY$
with i1 as (
INSERT INTO bilkaib (dokumnr)
select dok.dokumnr from dok join source on dok.dokumnr = source.dokumnr
returning *
)
select count(*) from i1;
$BODY$ language sql;

-- 调用前确保source临时表存在(你已经创建并插入数据)
select TestAddAssetTransactions();

方案选择建议

  • 单列少量数据:优先用数组方式,语法简单,无额外类型定义。
  • 多列数据或需要清晰语义:用自定义表类型,扩展性好。
  • 超大量数据:用临时表,避免数组内存限制。

内容的提问来源于stack exchange,提问作者Andrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:35:22