27

我想让 SQL 在 PostgreSQL 中删除一个函数。我编写DROP FUNCTION并从中获取函数名称pg_proc。那不是问题。但是,如果我留下空白参数,它将不会删除该函数。

我检查了手册并写了然后我必须用它的参数来识别函数来删除它,例如DROP FUNCTION some_func(text,integer)不仅仅是DROP FUNCTION some_func.

我在哪里可以找到参数?在pg_proc表中函数的行中没有参数。那么我怎样才能让 SQL 删除这个函数呢?

4

4 回答 4

39

Postgres 有一个专门的功能用于此目的。随 Postgres 8.4 引入。手册:

pg_get_function_identity_arguments(func_oid)...获取参数列表以识别函数(没有默认值)...

pg_get_function_identity_arguments返回标识函数所需的参数列表,例如,它需要出现在 within 中的形式ALTER FUNCTION。这种形式省略了默认值。

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

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

回报:

                  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,它返回一个完整的函数签名,包括参数类型:

-- 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;
于 2012-08-26T04:57:10.600 回答
1

使用 pgadminIII 并直接访问功能列表并右键单击它然后选择删除在此处输入图像描述

于 2014-02-12T03:48:21.623 回答
1

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

drop function if exists some_func;

请参阅文档

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

于 2018-04-27T09:15:08.343 回答
0

如果您正在使用旧版本的 postgres,其中 pg_get_function_identity_arguments(func_oid) 不存在,我创建自己的函数从函数中获取参数,您只需要传递函数的 oid,您需要部署下面的函数到您的 postgres 数据库。

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

    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 "public.getfunctionparameter(integer,text)"
2 "public.getfunctionparameter(oid)"
于 2017-12-28T19:49:38.713 回答