PostgreSQL 14 不支持标准 SQL 存储过程语法,CREATE PROCEDURE 会报错;需用 CREATE FUNCTION 替代,但其不支持函数内 COMMIT/ROLLBACK,且必须指定返回类型(如 RETURNS void),调用方式为 SELECT 或 PERFORM。

PostgreSQL 14 不支持标准 SQL 存储过程语法
PostgreSQL 14 没有实现 SQL 标准的 CREATE PROCEDURE(带 CALL 调用、支持事务控制语句如 COMMIT/ROLLBACK 的那种)。你如果直接写 CREATE PROCEDURE my_proc() AS ...,会报错:ERROR: syntax error at or near "PROCEDURE"。这是版本限制,不是配置或权限问题。
用 CREATE FUNCTION 替代,但要注意事务行为
实际开发中,绝大多数“想写存储过程”的需求,用 CREATE FUNCTION 就够了——只是它叫 function,不是 procedure。关键区别在于:
-
FUNCTION默认在事务内执行,不能主动COMMIT或ROLLBACK(除非用SECURITY DEFINER+dblink间接绕过,不推荐) - 调用方式是
SELECT my_func()或PERFORM my_func()(在另一个函数里),不是CALL my_proc() - 必须指定返回类型,哪怕只是
RETURNS void
示例:
CREATE OR REPLACE FUNCTION transfer_funds(
from_id INT,
to_id INT,
amount NUMERIC
) RETURNS void AS $$
BEGIN
UPDATE accounts SET balance = balance - amount WHERE id = from_id;
UPDATE accounts SET balance = balance + amount WHERE id = to_id;
-- 无法在这里写 COMMIT;整个函数随外部事务一起提交或回滚
END;
$$ LANGUAGE plpgsql;PostgreSQL 15+ 才真正支持 CREATE PROCEDURE
如果你确实需要 CALL、需要函数内独立事务(比如日志写入不被主事务回滚影响),那 PostgreSQL 14 做不到。必须升级到 15 或更高版本。15 引入了真正的 CREATE PROCEDURE,支持 COMMIT/ROLLBACK,且调用语法为 CALL transfer_funds(1, 2, 100.0)。
升级前务必确认:现有应用是否依赖函数的事务绑定行为?强行用 14 的 function 模拟 procedure,容易在异常路径下漏掉回滚或重复提交。
常见误操作和兼容性陷阱
有人试图在 14 里用 LANGUAGE sql 写多条语句的 function,结果失败——SQL 函数不支持变量、循环、条件分支,也**不允许包含多个命令**(除非用 DO 块,但那是匿名块,不能复用)。正确做法是:
- 简单查询封装 → 用
LANGUAGE sql+ 单条SELECT - 含逻辑控制、DML、错误处理 → 必须用
LANGUAGE plpgsql - 想让函数不被主事务回滚影响 → 14 无解,别硬套
dblink_exec或临时表模拟,维护成本高且易出竞态
另外,plpgsql 函数默认 VOLATILE,如果函数只读且确定性高,显式加 STABLE 或 IMMUTABLE 能提升查询计划缓存效率。

















