How to use a record type variable in plpgsql?
如何将存储在记录类型变量中的查询结果用于同一存储函数中的另一个查询? 我使用Postgres 9.4.4。
用这样的表:
1 2 3 | CREATE TABLE test (id INT, tags text[]); INSERT INTO test VALUES (1,'{a,b,c}'), (2,'{c,d,e}'); |
我写了一个函数(简化),如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 | CREATE OR REPLACE FUNCTION func(_tbl regclass) RETURNS TABLE (t TEXT[], e TEXT[]) LANGUAGE plpgsql AS $$ DECLARE t RECORD; c INT; BEGIN EXECUTE format('SELECT id, tags FROM %s', _tbl) INTO t; SELECT COUNT(*) FROM t INTO c; RAISE NOTICE '% results', c; SELECT * FROM t; END $$; |
...但是没有用:
1 | SELECT func('test'); |
1
2
3
4
5
6 ERROR: 42P01: relation"t" does NOT exist
LINE 1: SELECT COUNT(*) FROM t
^
QUERY: SELECT COUNT(*) FROM t
CONTEXT: PL/pgSQL FUNCTION func(regclass) line 7 at SQL statement
LOCATION: parserOpenTable, parse_relation.c:986
核心误解:
- PostgreSQL表变量
- 将多个行和列选择到一个记录变量中
因此,不能将多个行分配给
1 | EXECUTE format('SELECT id, tags FROM %s', _tbl) INTO t; |
... Postgres仅分配第一行,而丢弃其余行。由于查询中的"第一个"定义不正确,因此最终会被任意选择。显然是由于一开始提到的误解。
relation"t" does not exist
现在应该很清楚,
最后(即使其余的都可以),您的返回类型似乎是错误的:
您要尝试执行的操作如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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; |
调用(注意语法!):
1 | SELECT * FROM func('test'); |
有关:
- Postgres从动态sql字符串创建本地临时表(在提交删除时)
只是概念证明。在选择整个表时,您将只使用基础表。实际上,查询中将包含一些
注意潜伏类型不匹配时,
但是我完全替换了它,在
1 | GET DIAGNOSTICS _ct = ROW_COUNT; |
手册中的详细信息。
为什么
- 9.1下是否仍建议使用常规VACUUM ANALYZE?
撇开:普通SQL中的CTE通常可以胜任:
- 从plpgsql中的FOR循环切换到基于集合的SQL命令