postgresql中返回结果集必须用create function配合returns table或setof,因create procedure不支持returns子句、return query及结果集返回,仅能通过临时表或refcursor间接输出。

PostgreSQL里没有“存储过程返回值”这回事,RETURNS TABLE只属于函数
PostgreSQL 11+ 虽然引入了 CREATE PROCEDURE,但它**不支持 RETURNS 子句**,也不能用 RETURN 返回数据集。你看到的 RETURNS TABLE 只能用于 CREATE FUNCTION。如果目标是返回结果集(比如供 SELECT 调用),必须用函数,不是过程。
想返回表结构?用 CREATE FUNCTION ... RETURNS TABLE 是唯一正解
这是最常用、最直接的方式,语法清晰,调用自然:
CREATE OR REPLACE FUNCTION get_active_users()
RETURNS TABLE(id INT, name TEXT, last_login TIMESTAMPTZ) AS $$
BEGIN
RETURN QUERY SELECT u.id, u.name, u.last_login
FROM users u
WHERE u.status = 'active';
END;
$$ LANGUAGE plpgsql;
调用时就像查表一样:
SELECT * FROM get_active_users();
- 返回列名和类型由
RETURNS TABLE(...)显式声明,不是靠函数体推断 - 必须用
RETURN QUERY(不能用RETURN加单个值) - 函数语言可以是
plpgsql、sql,甚至python(需启用plpython3u) - 若用
LANGUAGE sql,可省略BEGIN/END,直接写SELECT(但无法做条件判断或变量)
为什么不能把 RETURNS TABLE 塞进 CREATE PROCEDURE?
因为过程的设计定位就是“执行动作”,不是“提供数据”。它的限制很明确:
-
CALL get_active_users();会报错:ERROR: procedure get_active_users() does not exist(即使同名函数存在) - 过程内部不能用
RETURN QUERY;RETURN只能结束执行,不带值 - 过程不支持
OUT参数返回结果集(不像 Oracle 或 SQL Server) - 过程无法被
FROM子句引用,也就没法在SELECT中“当表用”
真需要过程 + 返回数据?只能靠临时表或 REFCURSOR
如果业务逻辑复杂、必须用过程(比如含事务控制、多步 DML),又需要把结果“交出去”,有两个现实选项:
- 写入临时表:
CREATE TEMP TABLE result_cache AS SELECT ...,再让应用去查这个临时表(注意生命周期只在当前会话) - 用
REFCURSOR输出游标(适合客户端主动FETCH):CREATE OR REPLACE PROCEDURE fetch_user_cursor(OUT curs REFCURSOR) AS $$ BEGIN OPEN curs FOR SELECT id, name FROM users WHERE status = 'active'; END; $$ LANGUAGE plpgsql;
然后:
BEGIN; CALL fetch_user_cursor('mycur'); FETCH ALL IN mycur; COMMIT;
这两种方式都绕开了“返回值”概念,本质是副作用输出——不是函数那种声明式契约,容易漏清理、难测试、对应用更不友好。
真正要“像函数一样返回表”,就别碰 PROCEDURE。名字叫 get_、list_ 的东西,一律用 FUNCTION 实现,这是 PostgreSQL 的约定和限制所在。










