You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL 11 如何修改demoproc函数以适配同名不同参数的存储过程

问题原因
  • PostgreSQL 允许存储过程重载(同一模式下同名但参数列表不同),仅通过模式名+存储过程名无法唯一标识目标对象,必须补充参数类型签名才能准确定位到要修改的存储过程
  • 你原有代码还存在语法错误:ALTER PROCEDURE %I.%I( owner to %I 语法非法,缺少右括号,也不符合ALTER对象所有者的标准语法规范
修改方案1:精准指定参数类型,修改单个重载存储过程

这个方案需要额外传入参数类型列表,唯一标识目标存储过程

修改后的函数代码

CREATE OR REPLACE FUNCTION public.demoproc(
    i_schemaname character varying, 
    i_objectname character varying, 
    i_arg_types character varying[], -- 新增参数:存储过程的参数类型列表,比如'{integer, varchar}'
    i_t_owner character varying
) RETURNS text
LANGUAGE plpgsql SECURITY DEFINER
AS $$
declare
    v_statement text ;
    v_arg_sign text;
begin
    -- 拼接参数类型签名,比如 integer, character varying
    SELECT string_agg(trim(both ' ' from arg_type), ',') INTO v_arg_sign
    FROM unnest(i_arg_types) arg_type;

    -- 修正ALTER语法,拼接完整的存储过程标识
    v_statement := FORMAT(
        'ALTER PROCEDURE %I.%I(%s) OWNER TO %I',
        i_schemaname,
        i_objectname,
        v_arg_sign,
        i_t_owner
    );
    EXECUTE v_statement;

    return FORMAT('PROCEDURE "%I"."%I"(%s) 所有者已修改为 "%I"',
        i_schemaname,
        i_objectname,
        v_arg_sign,
        i_t_owner
    );
END;
$$;

调用示例

要修改schema_name下参数为int, varchar的demo_proc存储过程的所有者为new_user,调用方式如下:

select public.demoproc('schema_name', 'demo_proc', '{integer, character varying}', 'new_user');
修改方案2:批量修改同名所有重载存储过程的所有者

如果不需要精准指定,想一次性修改同一模式下同名称所有重载存储过程的所有者,可以用这个版本,不需要调整原有调用逻辑

修改后的函数代码

CREATE OR REPLACE FUNCTION public.demoproc(
    i_schemaname character varying, 
    i_objectname character varying, 
    i_t_owner character varying
) RETURNS text
LANGUAGE plpgsql SECURITY DEFINER
AS $$
declare
    v_proc_record record;
    v_modified_count integer := 0;
begin
    -- 遍历pg_proc系统表,匹配所有符合名称和模式的存储过程
    FOR v_proc_record IN 
        SELECT proname, pronargs, pg_get_function_arguments(p.oid) as arg_sign
        FROM pg_proc p
        JOIN pg_namespace n ON p.pronamespace = n.oid
        WHERE n.nspname = i_schemaname
          AND p.proname = i_objectname
          AND p.prokind = 'p' -- 只匹配存储过程,排除普通函数
    LOOP
        EXECUTE FORMAT(
            'ALTER PROCEDURE %I.%I(%s) OWNER TO %I',
            i_schemaname,
            i_objectname,
            v_proc_record.arg_sign,
            i_t_owner
        );
        v_modified_count := v_modified_count + 1;
    END LOOP;

    return FORMAT('共修改 %s 个名为 "%I"."%I" 的存储过程,所有者已全部修改为 "%I"',
        v_modified_count,
        i_schemaname,
        i_objectname,
        i_t_owner
    );
END;
$$;

调用示例

调用方式和你原来的完全一致:

select public.demoproc('schema_name', 'function_name', 'username');

内容的提问来源于stack exchange,提问作者Adam Mulla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:06:00