问题描述
我有 Postgres 函数,它需要迭代一个数组表名,并且应该将每次从查询返回的值保存到数组中。 也许这不是正确的方法,所以如果有更好的方法,我会很高兴知道:) 我尝试使用 format 函数每次生成不同的查询。
CREATE OR REPLACE FUNCTION array_iter(tables_name text[],idd integer)
RETURNS void
LANGUAGE 'plpgsql'
AS $BODY$
declare
current_table text;
current_height integer :=0;
quer text;
heights integer[];
begin
FOREACH current_table IN ARRAY $1
LOOP
quer:=format('SELECT height FROM %s WHERE %s.idd=$2',current_table);
current_height:=EXECUTE quer;
SELECT array_append(heights,current_height);
END LOOP;
RAISE NOTICE '%',heights;
end;
$BODY$;
解决方法
首先,您迫切需要更新您的 Postgres,因为 9.1 版不再受支持,并且已经有 5 年没有支持了(2016 年 10 月)。我建议去 v13,因为它是最新的,但绝对最低到 10.12。在失去支持之前,它仍然需要一年多一点的时间(2022 年 11 月)。所以考虑到这一点。
语句 quer:=format('SELECT height FROM %s WHERE %s.idd=$2',current_table);
无效,它包含 2 个格式说明符但只有 1 个参数。您可以通过在每个说明符上包含参数编号来使用单个参数。所以quer:=format('SELECT height FROM %1s WHERE %1s.idd=$2',current_table);
。但这不是必需的,因为第二个是表别名,它不需要是表名,因为您根本不需要 1 个表。但是,我会将参数 ($2) 从选择中移出并为其使用格式说明符/参数。
语句 current_height:=EXECUTE quer;
同样无效,您不能将赋值的 Right Val 设为选择。为此,您可以使用语句后面的 INTO 选项。 execute query into ...
。
虽然 SELECT array_append(heights,current_height);
是一个有效的语句,但简单的赋值 heights = heights || current_height;
似乎更容易(至少恕我直言)。
最后有几个遗漏。在运行动态 SQL 语句之前,最好在执行之前“打印”或记录该语句。当语句有错误时会发生什么。以及为什么构建一个函数来完成所有这些工作只是为了丢弃结果,而不是返回整数数组(integer[])而不是 void。
所以我们到达:
create or replace function array_iter(tables_name text[],idd integer)
returns integer[]
language plpgsql
as $$
declare
current_table text;
current_height integer :=0;
quer text;
heights integer[];
begin
foreach current_table in array tables_name
loop
quer:=format('select height from %I where id=%s',current_table,idd);
raise notice 'Running Query:: %',quer;
execute quer into current_height;
heights = heights || current_height;
end loop;
raise notice '%',heights;
return heights;
exception
when others then
raise notice 'Query failed:: SqlState:%,ErrorMessage:%',sqlstate,sqlerrm;
raise;
end;
$$;
这确实可以在 9.5 之前的版本上运行(请参阅 fiddle),尽管我不能说它可以在更旧的 9.1 上运行。