PostgreSQL存储过程不支持DEFAULT关键字声明参数默认值,proargdefaults字段对PROCEDURE始终为空,唯一可靠方式是改用FUNCTION或在过程体内用COALESCE/IF手动兜底。

PostgreSQL 存储过程不支持 DEFAULT 关键字声明参数默认值
直接在 CREATE PROCEDURE 的参数列表里写 p_id INT DEFAULT 1 会报错:ERROR: syntax error at or near "DEFAULT"。PostgreSQL 的存储过程(PROCEDURE)语法上**完全不接受 DEFAULT 子句**——这和函数(FUNCTION)不同,也和 SQL Server、MySQL 的行为不一致。
pg_get_functiondef() 解析不到存储过程的默认参数值
即使你误以为写了默认值,或者看到别人用函数方式“绕过”了限制,pg_get_functiondef(oid) 对存储过程返回的定义里也不会包含任何 = ... 形式,默认值根本不存在于元数据中。原因很直接:proargdefaults 字段只对 FUNCTION 生效,对 PROCEDURE 始终是 NULL 或空 bytea。
- 查
pg_proc表时,prokind = 'p'(procedure)的记录,proargdefaults字段基本不可用 - 试图用
convert_from(proargdefaults, 'UTF8')强转只会得到乱码或空字符串 - 正则匹配
DEFAULT或=在存储过程定义文本中注定失败——它压根不会出现在那里
真正能用默认值的只有 FUNCTION,且必须手动处理调用逻辑
如果你确实需要默认参数行为,唯一可靠路径是改用 FUNCTION,并显式返回 void 或忽略返回值。例如:
CREATE OR REPLACE FUNCTION update_user_status(
p_user_id INT,
p_status TEXT DEFAULT 'active'
) RETURNS void AS $$
BEGIN
UPDATE users SET status = p_status WHERE id = p_user_id;
END;
$$ LANGUAGE plpgsql;
- 调用时可省略参数:
SELECT update_user_status(123);,p_status自动为'active' - 但 ORM(如 SQLAlchemy、Django)传
None仍会作为NULL显式传入,不会触发默认值——必须由客户端逻辑判断是否省略该参数 - 如果必须用
CALL语法(比如兼容旧流程),就只能把默认值逻辑移到过程体内部,用COALESCE(p_status, 'active')或IF p_status IS NULL THEN ...手动兜底
容易被忽略的关键点:INOUT 参数不能“自动填充”,只能靠过程体赋值
有人尝试用 INOUT 模拟默认值,比如 p_flag INOUT BOOLEAN DEFAULT true ——这语法非法,且即使改成 INOUT 参数,它的初始值仍是 NULL,除非调用方明确传值。过程体内可以写 p_flag := COALESCE(p_flag, true),但这属于业务逻辑兜底,不是数据库层的默认值机制。
归根结底,PostgreSQL 的存储过程设计就是“无默认参数”的。想省事,就用函数;想用 CALL,就得自己在过程里做 IS NULL 判断——别指望解析 definition 文本或查系统视图能捞出不存在的东西。










