芯误解:一个record
变量保存一个单个行(或是NULL),而不是一个表(公知类型的0-n行).Postgres或PL/pgSQL中没有"表变量".根据任务的不同,有各种替代方案:
PostgreSQL表变量
将多个行和列选择为记录变量
因此,您不能将多行分配给record
类型变量.在这个声明中:
EXECUTE format('SELECT id, tags FROM %s', _tbl) INTO t;
... Postgres 只分配第一行并丢弃其余部分.由于"第一个"在您的查询中没有很好地定义,因此您最终会选择一个任意选择.显然是由于一开始就提到的误解.
一个record
变量也可以不到位SQL查询表的使用.这是导致错误的主要原因:
关系"t"不存在
现在应该很清楚,count(*)
开始时没有任何意义,因为t
只是一个记录/行 - 除此之外不可能.
最后(即使其余部分都有效),你的返回类型似乎错了:.因为你选择(t TEXT[], e TEXT[])
id, tags
了t
,你想要返回类似的东西(id int, e TEXT[])
.
你想要做的是这样的:
CREATE OR REPLACE FUNCTION func(_tbl regclass) RETURNS TABLE (id int, e text[]) AS $func$ DECLARE _ct int; BEGIN EXECUTE format( 'CREATE TEMP TABLE tmp ON COMMIT DROP AS SELECT id, tags FROM %s' , _tbl); GET DIAGNOSTICS _ct = ROW_COUNT; -- cheaper than another count(*) -- ANALYZE tmp; -- if you are going to run multiple queries RAISE NOTICE '% results', _ct; RETURN QUERY TABLE tmp; END $func$ LANGUAGE plpgsql;
调用(注意语法!):
SELECT * FROM func('test');
有关:
Postgres从动态sql字符串创建本地临时表(在提交下拉列表中)
只是一个概念证明.在选择整个表时,您只需使用基础表.实际上你WHERE
在查询中会有一些条款......
小心潜伏类型不匹配,count()
返回bigint
,您无法将其分配给integer
变量.需要演员:count(*)::int
.
但是我完全取代了它,之后运行它会更便宜EXECUTE
:
GET DIAGNOSTICS _ct = ROW_COUNT;
手册中的详细信息.
为什么ANALYZE
?
是否仍在9.1推荐常规VACUUM ANALYZE?
另外:普通SQL中的CTE通常可以完成这项工作:
从plpgsql中的FOR循环切换到基于集合的SQL命令