DROP FUNCTION不知道参数的数量/类型?

Ste*_*son 43 postgresql dynamic-sql plpgsql sql-drop

我将所有功能都保存在一个文本文件中'CREATE OR REPLACE FUNCTION somefunction'.因此,如果我添加或更改某些功能,我只需将文件提供给psql.

现在,如果我向现有函数添加或删除参数,它会创建一个具有相同名称的重载,并按照确切的顺序删除所有参数类型中的原始I类型,这是一种单调乏味的操作.

是否有某种通配符,我可以使用DROP具有给定名称的所有函数,所以我可以添加DROP FUNCTION行到我的文件的顶部?

Erw*_*ter 68

基本查询

此查询创建所有必需的DDL语句(使用强制转换为简化regprocedure):

SELECT 'DROP FUNCTION ' || oid::regprocedure
FROM   pg_proc
WHERE  proname = 'my_function_name'  -- name without schema-qualification
AND    pg_function_is_visible(oid);  -- restrict to current search_path ..
                                     -- .. you may or may not want this
Run Code Online (Sandbox Code Playgroud)

输出:

DROP FUNCTION my_function_name(string text, form text, maxlen integer);
DROP FUNCTION my_function_name(string text, form text);
DROP FUNCTION my_function_name(string text);
Run Code Online (Sandbox Code Playgroud)

执行命令(在合理性检查之后).

函数名称区分大小写,并且在作为text参数匹配时传递时没有添加双引号pg_proc.proname.

对象标识符type regprocedure(oid::regprocedure)的强制转换使得所有标识符都可以安全地防止SQL注入(通过恶意格式错误的标识符).转换为时text,函数名称将根据search_path需要自动根据当前双引号和模式限定.

pg_function_is_visible(oid)将选择限制为当前的功能search_path.你可能想要也可能不想要那样.在条件pg_function_is_visible(oid)到位的情况下,保证功能可见.

如果在多个模式中有多个相同名称的函数,或者具有各种函数参数的重载函数,则所有这些函数将单独列出.您可能希望限制为特定架构或特定功能参数.

有关:

功能

您可以plpgsql围绕此构建一个函数来立即执行语句EXECUTE.对于Postgres 9.1或更高版本: 小心!它会降低你的功能!

CREATE OR REPLACE FUNCTION f_delfunc(_name text, OUT func_dropped int) AS
$func$
DECLARE
   _sql text;
BEGIN
   SELECT count(*)::int
        , 'DROP FUNCTION ' || string_agg(oid::regprocedure::text, '; DROP FUNCTION ')
   FROM   pg_proc
   WHERE  proname = _name
   AND    pg_function_is_visible(oid)
   INTO   func_dropped, _sql;  -- only returned if trailing DROPs succeed

   IF func_dropped > 0 THEN    -- only if function(s) found
     EXECUTE _sql;
   END IF;
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

呼叫:

SELECT * FROM f_delfunc('my_function_name');
Run Code Online (Sandbox Code Playgroud)

要不就:

SELECT f_delfunc('my_function_name');
Run Code Online (Sandbox Code Playgroud)

这样您就不会获得结果列的列 func_dropped.对你来说可能无关紧要.

该函数返回找到和删除的函数数(没有异常引发) - 0如果没有找到.

它假定一个(默认)search_path,其中pg_catalog尚未搬来搬去.
更多相关答案:

对于Postgres版本早于9.1或更早版本的函数使用regprocpg_get_function_identity_arguments(oid)检查此答案的编辑历史记录.

  • 我觉得`psql -E`非常有用.这就是我对'pg_catalog.pg_get_function_arguments(p.oid)`的想法. (4认同)
  • @Andrus:我更新了一个改进的功能来处理这个问题. (2认同)

Pau*_*ora 22

您需要编写一个带有函数名称的函数,并使用其参数类型查找每个重载information_schema,然后DROP为每个重载生成并执行a .

编辑:事实证明这比我想象的要困难得多.看起来information_schema似乎没有在其routines目录中保留必要的参数信息.所以你需要使用PostgreSQL的补充表pg_procpg_type:

CREATE OR REPLACE FUNCTION udf_dropfunction(functionname text)
  RETURNS text AS
$BODY$
DECLARE
    funcrow RECORD;
    numfunctions smallint := 0;
    numparameters int;
    i int;
    paramtext text;
BEGIN
FOR funcrow IN SELECT proargtypes FROM pg_proc WHERE proname = functionname LOOP

    --for some reason array_upper is off by one for the oidvector type, hence the +1
    numparameters = array_upper(funcrow.proargtypes, 1) + 1;

    i = 0;
    paramtext = '';

    LOOP
        IF i < numparameters THEN
            IF i > 0 THEN
                paramtext = paramtext || ', ';
            END IF;
            paramtext = paramtext || (SELECT typname FROM pg_type WHERE oid = funcrow.proargtypes[i]);
            i = i + 1;
        ELSE
            EXIT;
        END IF;
    END LOOP;

    EXECUTE 'DROP FUNCTION ' || functionname || '(' || paramtext || ');';
    numfunctions = numfunctions + 1;

END LOOP;

RETURN 'Dropped ' || numfunctions || ' functions';
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
Run Code Online (Sandbox Code Playgroud)

我在一个重载函数上成功测试了这个.它被拼凑得非常快,但作为实用功能可以正常工作.我建议在实践中使用它之前测试更多,以防我忽略了一些东西.


Сух*_*й27 6

改进原始答案以考虑schema到,即。schema.my_function_name,

select
    format('DROP FUNCTION %s(%s);',
      p.oid::regproc, pg_get_function_identity_arguments(p.oid))
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE
    p.oid::regproc::text = 'schema.my_function_name';
Run Code Online (Sandbox Code Playgroud)