关于postgresql:如何获取函数参数列表(所以我可以删除一个函数)

How to get function parameter lists (so I can drop a function)

我想让SQL在PostgreSQL中删除一个函数。我写了DROP FUNCTION和一个来自pg_proc的get函数名。这不是问题。但是,如果我保留空白参数,它将不会删除函数。

我检查了手册,然后写了一篇文章,然后我必须用它的参数来识别函数,比如DROP FUNCTION some_func(text,integer),而不仅仅是DROP FUNCTION some_func

在哪里可以找到参数?在pg_proc表中的函数行on中没有参数。那么,如何让SQL删除函数呢?


Postgres为此有专门的功能。与Postgres 8.4一起介绍。手册:

pg_get_function_identity_arguments(func_oid) ... get argument list to identify a function (without default values) ...

pg_get_function_identity_arguments returns the argument list
necessary to identify a function, in the form it would need to appear
in within ALTER FUNCTION, for instance. This form omits default values.

使用它(和postgres 9.1中引入的format()语句),下面的查询生成DDL语句以删除与搜索词匹配的函数:

1
2
3
4
5
6
7
8
9
10
11
12
SELECT format('DROP %s %I.%I(%s)'
            , CASE WHEN p.proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
            , n.nspname
            , p.proname
            , pg_catalog.pg_get_function_identity_arguments(p.oid)
             ) AS stmt
FROM   pg_catalog.pg_proc p
JOIN   pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE  p.proname = 'dblink'                     -- function name
-- AND n.nspname = 'public'                     -- schema name (optional)
-- AND pg_catalog.pg_function_is_visible(p.oid) -- function visible to user
ORDER  BY 1;

Postgres 11中的系统目录pg_proc发生了变化。proisaggprokind取代,增加了真正的存储过程。你需要适应。见:

  • 如何在PostgreSQL中删除所有函数?

返回:

1
2
3
4
5
6
                  stmt
---------------------------------------------------
 DROP FUNCTION public.dblink(text);
 DROP FUNCTION public.dblink(text, BOOLEAN);
 DROP FUNCTION public.dblink(text, text);
 DROP FUNCTION public.dblink(text, text, BOOLEAN);

在示例中找到四个匹配项,因为dblink使用重载函数。有选择地运行DROP语句!

或者,可以使用方便的对象标识符类型regprocedure的强制转换,该类型返回完整的函数签名,包括参数类型:

1
2
3
4
5
6
7
8
-- SET LOCAL search_path = '';  -- optional, to get all names schema-qualified
SELECT format('DROP %s %s;'
            , CASE WHEN proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
            , oid::regprocedure
             ) AS stmt
FROM   pg_catalog.pg_proc
WHERE  proname = 'dblink'   -- function name
ORDER  BY 1;


在Postgres10中,只要函数在其模式中是唯一的,就可以在不知道参数列表的情况下删除它。

1
DROP FUNCTION IF EXISTS some_func;

看文档。

当然,如果您已经重载了函数(或者试图删除多个模式),您仍然需要以上的答案。


使用pgadminiii并直接访问函数列表,右键单击该列表,然后选择"删除MGXY1"〔0〕。


如果您正在使用以前版本的postgres,其中pg get func t i on identity arguments(func oid)不存在,我创建自己的函数从函数中获取参数,您只需要传递函数的oid,您需要将下面的函数部署到postgres db。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CREATE OR REPLACE FUNCTION public.getFunctionParameter(functionOid oid)
  RETURNS text AS
$BODY$

DECLARE
    t_paras text;
    paras oid[];
    res text :='(';
BEGIN

SELECT proargtypes INTO t_paras FROM pg_proc WHERE oid=functionOid;
IF t_paras IS NULL OR t_paras='' THEN
    RETURN '()';
ELSE
    paras:=string_to_array(t_paras,' ');
    FOR i IN  array_lower(paras,1) .. array_upper(paras,1)
    loop
        raise notice 'para is %',paras[i];
        SELECT format_type(paras[i]::oid,NULL) INTO t_paras;
        res:=res||t_paras||',';
    END loop;
    res:=SUBSTRING(res FROM 1 FOR CHAR_LENGTH(res)-1);
    res:=res||')';
    RETURN res;
END IF;

END

    $BODY$
      LANGUAGE plpgsql ;

下面的函数将列出函数名和参数,如果要在其他模式下获取函数,请更改模式名,例如,我正在使用public

1
2
3
    SELECT n.nspname||'.'||p.proname||public.getFunctionParameter(p.oid)
FROM    pg_proc p JOIN   pg_namespace n ON n.oid = p.pronamespace
WHERE  n.nspname='public'

结果如下

1
2
1"public.getfunctionparameter(integer,text)"
2"public.getfunctionparameter(oid)"