如果您想使用函数来处理查询的结果集,最好的选择是SELECT ... INTO TEMPORARY TABLE,然后使用临时表名调用该函数。
考虑到生成的行集非常简单,在 PostgreSQL 函数中使用行集非常困难。我知道的唯一方法是使用 refcursor、处理临时表或实现聚合或窗口函数。后两个选项不允许您控制返回的行数,因此它们不适合您的目的。
函数不能引用调用函数的 CTE 中的常用表表达式别名,因此不能使用 CTE 创建虚拟表并将表的名称传递给函数。显示它不起作用的示例:
CREATE OR REPLACE FUNCTION dynsql(tname text, colname text) RETURNS SETOF RECORD AS
$$
BEGIN
RETURN QUERY EXECUTE format('SELECT %I FROM %I', colname, tname);
END;
$$ LANGUAGE plpgsql;
WITH dummy(col) AS (VALUES (1),(2),(3))
SELECT * FROM dynsql('dummy','col') t(id integer);
结果:
ERROR: relation "dummy" does not exist
...因为WITH 表达式中的别名是WITH 表达式的本地别名。 (能够从函数中引用它会很好,但这也会产生各种令人兴奋的名称冲突问题和SECURITY DEFINER 函数的安全问题。)
虽然您可以编写一个使用 refcursor 的 PL/PgSQL 函数,但这需要您通过查询 DECLARE 一个游标并将其传递给函数。您不能只使用普通的函数调用语法。它的效率也很低,需要在函数中使用LOOPing。我认为这不会有太大帮助。
实现该功能时,使用EXECUTE format(...) USING ... 保持动态SQL 不会太可怕。见this earlier answer。