下面的代码不是一个完整的设置,你可以运行检查。它应该只是让它更清楚一点的问题是什么。
对于这样的示例函数(变量示例取自PostgreSQL inserting list of objects into a stored procedure或PostgreSQL - Passing Array to Stored Function):
CREATE OR REPLACE function get_v(variadic _v text[]) returns table (v varchar(50)) as
$F$
declare
begin
return query
select t.v
from test t
where t.v = any(_v)
end;
$F$
language plpgsql
;
如果手动复制select string_agg...
查询的单值输出'x','y','z'
,并将其作为函数的参数,则函数将起作用:
SELECT v FROM get_v_from_v(
'x','y','z'
);
'x','y','z'
作为variadic _v text[]
读入函数,以便函数可以使用where t.v = any(_v)
检查其值。
如果将'x','y','z'
输出后面的(select string_agg...)
查询放在同一位置,则函数将不起作用:
select v from get_v_from_v(
(select string_agg(quote_literal(x.v), ',') from (select v from get_v_from_name('something')) as x)
);
这意味着:(select string_agg...)
查询得到的"单值输出字段" 'x','y','z'
与text[]
列表类型不同:'x','y','z'
.
用get_v_from_name('something')
作为另一个函数,它返回一个表的一列和行中的"v"值,在它的输出上运行string_agg()
之后,你会得到'x','y','z'
的输出。我在How to make a list of quoted strings from the string values of a column in postgresql?学习了这个工作函数string_agg()
。这样的字符串函数的完整列表在9.4. String Functions and Operators的PostgreSQL指南中。
我猜select
查询输出的格式只是一个字符串,而不是一个列表,这样输入就不会被看作是一个带引号的字符串列表,而更像是一个完整的字符串:''x','y','z''
。get_v_from_v
参数不仅需要所有值的一个字符串,还需要一个带引号的字符串列表,因为函数的参数是text[]
类型,这是一个列表。
看起来这个问题并不取决于输出背后的查询,而只是一个一般性的问题,即表元组中的输出并作为函数的参数,与作为同一参数手工复制的同一输出并不相同。
因此,问题来了:要使select
查询的输出与其输出的手工拷贝相同,以便输出只是列表'x','y','z'
,就好像它只是被复制和粘贴一样,需要做些什么?
附言:我猜这种从一列表输出中制作引用字符串列表并只将其传递给函数的方式并不是最佳实践。例如,在TSQL/SQL Server中,您应该传递"表值参数",以便将值作为从函数中选择的表传递以获取值,请参见How do I pass a list as a parameter in a stored procedure?。不确定在PostgreSQL中如何做到这一点,但这可能正是我们需要的。
1条答案
按热度按时间h7appiyu1#
get_v_from_name('something')
作为另一个函数,返回一个表,表中只有一列,行中有“v”值(问题中已经提到),下面的函数起作用:旁注:
array_agg(quote_literal(x.v), ',')
而不是array_agg(x.v)
失败,函数不允许第二个参数。