从SQL Server转PostgreSQL:如何实现含临时表的存储过程?
嘿,太懂你这种讨厌嵌套查询的心情了——可读性差不说,后期维护简直头疼!从SQL Server转PostgreSQL确实会遇到一些语法小差异,但复刻你这个存储过程的逻辑其实很简单,咱们一步步来:
核心思路:临时表 + 结果返回
PostgreSQL支持临时表,行为和SQL Server的#Temptable本地临时表类似(会话级可见,会话结束自动销毁),而且可以在同一个存储逻辑里直接复用。不过PostgreSQL里**函数(Function)**比存储过程(Procedure)更适合直接返回结果集,和你SQL Server里存储过程的行为最匹配,咱们先看这个方案:
方案1:用PL/pgSQL函数复刻(推荐,直接返回结果)
CREATE OR REPLACE FUNCTION procname() -- 如果明确知道返回列的类型,建议写具体的表结构,比如 RETURNS TABLE(col_1 INT, col3 VARCHAR(100)) RETURNS SETOF record LANGUAGE plpgsql AS $$ BEGIN -- 方式1:用CREATE TEMP TABLE创建临时表(更常用) CREATE TEMP TABLE IF NOT EXISTS temptable AS SELECT s.col_1, s.col_2 FROM somewhere s; -- 方式2:你提到的SELECT INTO写法也支持,和上面等价 -- SELECT s.col_1, s.col_2 INTO TEMP TABLE temptable FROM somewhere s; -- 返回最终的关联查询结果,和SQL Server里最后那个SELECT的效果一致 RETURN QUERY SELECT t.col_1, se.col3 FROM temptable t INNER JOIN somewhere_else se ON se.col_2 = t.col_2; -- 可选:如果想用完立刻删除临时表,加这句(默认会话结束自动销毁) DROP TABLE IF EXISTS temptable; END; $$;
调用的时候直接执行:
SELECT * FROM procname();
小提示:如果能明确返回列的类型,把
RETURNS SETOF record改成RETURNS TABLE(col_1 你的类型, col3 你的类型),这样调用时不用额外指定列信息,更方便。
方案2:用PostgreSQL存储过程(适合需要事务控制的场景)
如果你确实想用PROCEDURE(PostgreSQL 11+支持),因为它支持事务提交/回滚等操作,但要注意:PROCEDURE本身不能直接返回结果集,需要先创建临时表,调用后再查询临时表:
CREATE OR REPLACE PROCEDURE procname() LANGUAGE plpgsql AS $$ BEGIN CREATE TEMP TABLE IF NOT EXISTS temptable AS SELECT s.col_1, s.col_2 FROM somewhere s; END; $$;
调用步骤:
- 执行存储过程:
CALL procname(); - 查询临时表获取结果:
SELECT t.col_1, se.col3 FROM temptable t INNER JOIN somewhere_else se ON se.col_2 = t.col_2;
额外注意事项
- PostgreSQL的临时表默认是会话级的,只有当前连接能访问,关闭连接后自动销毁;如果想让临时表在事务结束就销毁,创建时可以加
ON COMMIT DROP:CREATE TEMP TABLE temptable ON COMMIT DROP AS SELECT ...; - 标识符(表名、列名)默认大小写不敏感,建议全部用小写,避免加双引号的麻烦。
内容的提问来源于stack exchange,提问作者Henrik Poulsen




