删除命名空间中的所有函数?(执行生成的DDL命令?)

Har*_*wig 4 sql postgresql dynamic-sql plpgsql

我正在尝试编写一个命令来删除命名空间中的所有函数。我已经找到了一个可以生成删除函数脚本的命令:

SELECT 'DROP FUNCTION ' || ns.nspname || '.' || proname || '('
     || oidvectortypes(proargtypes) || ');'
FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid)
WHERE ns.nspname = 'public'  order by proname;
Run Code Online (Sandbox Code Playgroud)

资料来源:http ://www.postgresonline.com/journal/archives/74-How-to-delete-many-functions.html

这将生成类似以下内容的内容:

                 ?column?                 
------------------------------------------
 DROP FUNCTION public.function1(bigint);
 DROP FUNCTION public.function2();
 DROP FUNCTION public.function3(text);
Run Code Online (Sandbox Code Playgroud)

但是,我不知道如何更改代码,以便实际上删除函数 - 而不是仅生成命令。

有任何想法吗?

Erw*_*ter 6

Postgres 11中的系统目录发生了变化!(prokind而不是proisagg)参见:


可能看起来像这样:

CREATE OR REPLACE FUNCTION public.f_delfunc(_schema text, _del text = '')
  RETURNS text AS
$func$
DECLARE
   _sql   text;
   _ct    text;
BEGIN
   SELECT INTO _sql, _ct
          string_agg('DROP '
                   || CASE p.proisagg WHEN true THEN 'AGGREGATE '
                                                ELSE 'FUNCTION ' END
                   || quote_ident(n.nspname) || '.' || quote_ident(p.proname)
                   || '('
                   || pg_catalog.pg_get_function_identity_arguments(p.oid)
                   || ')'
                    , E'\n'
          )
          ,count(*)::text
   FROM   pg_catalog.pg_proc p
   LEFT   JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
   WHERE  n.nspname = _schema;
   -- AND p.proname ~~* 'f_%';                     -- Only selected funcs?
   -- AND pg_catalog.pg_function_is_visible(p.oid) -- Only visible funcs?

   IF _ct = '0' THEN
      RETURN 'Found 0 functions to delete';
   ELSIF lower(_del) = 'del' THEN                        -- Actually delete!
      EXECUTE _sql;
      RETURN _ct || E' functions deleted:\n' || _sql;
   ELSE                                               -- Else only show SQL.
      RETURN _ct || E' functions to delete:\n' || _sql;
   END IF;
END
$func$  LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

来电显示:

SELECT f_delfunc('public');         -- 2nd parameter is covered by default.
Run Code Online (Sandbox Code Playgroud)

调用删除:

SELECT f_delfunc('public','del');
Run Code Online (Sandbox Code Playgroud)

主要观点

  • 为此,您需要动态 SQL。将plpgsql 函数DO 语句(PostgreSQL 9.0+) 与EXECUTE.

  • 请注意函数pg_get_function_identity_arguments()pg_function_is_visible的使用。后者可以省略。这是一种保护措施,因此您不会删除当前用户的search_path.

  • 我添加了“安全模式”。仅删除如果$2 = 'del'. 否则只显示生成的 SQL。

  • 请注意,如果该函数位于您从中删除的架构中,它将删除自身。

  • 我还添加了quote_ident()防范SQLi 的功能。考虑以下:

CREATE FUNCTION "; DELETE FROM users;"()
  RETURNS int AS
'SELECT 1'
  LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
  • 如果任何涉及的函数存在依赖性,则此操作会失败。可以通过添加 来解决CASCADE,但我在这里没有这样做,因为它使该函数更加危险。

有关的: