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

时间:2011-11-29 21:09:51

标签: sql postgresql plpgsql dynamic-sql

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

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;

来源: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);

但是,我无法弄清楚如何更改代码,以便实际删除这些功能 - 而不是仅生成命令。

有什么想法吗?

5 个答案:

答案 0 :(得分:4)

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;

致电展示:

SELECT f_delfunc('public');         -- 2nd parameter is covered by default.

致电删除:

SELECT f_delfunc('public','del');

重点

  • 您需要动态SQL。使用plpgsql functionDO statement(PostgreSQL 9.0 +)与EXECUTE

  • 请注意使用functions pg_get_function_identity_arguments() and pg_function_is_visible。后者可以省略。这是一种安全措施,因此您不会删除当前用户search_path之外的功能。

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

  • 请注意,如果函数存在于您删除的架构中,将自行删除

  • 我还添加了quote_ident()来防范 SQLi 。请考虑以下事项:

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

相关:

答案 1 :(得分:0)

只需将查询的输出复制+粘贴到psql解释器中即可。它将运行您粘贴的所有命令。

答案 2 :(得分:0)

对于生成一组命令的任何SQL表达式:

begin;
create function _execute(text) returns boolean language plpgsql as $$
  begin
    raise info 'Execute: %', $1;
    execute $1;
  end;
$$;
select count(_execute(__SQL__)); -- __SQL__ is your command-generating statement
drop function _execute(text);
end;

答案 3 :(得分:0)

没有存储过程的我的版本

DO $$DECLARE command text;
BEGIN
command = (SELECT 'DROP FUNCTION ' || proname || '(' || oidvectortypes(proargtypes) || ')'
FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid)
WHERE proname='functioniliketodrop'
order by proname);
execute command;    
END$$;

答案 4 :(得分:0)

-- DROP FUNCTION public.f_deleteAllFunctions();

CREATE OR REPLACE FUNCTION public.f_deleteAllFunctions()
  RETURNS TABLE(functiondef character varying) AS
$BODY$ 

DECLARE 
var_r record;
var_query TEXT;

BEGIN

FOR var_r IN(
        SELECT  ns.nspname || '.' || proname || '(' || oidvectortypes(proargtypes) || ');' as nombreFuncion
        FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid)
        WHERE ns.nspname = 'public'  order by proname
        )

    LOOP
        functionDef := 'DROP FUNCTION ' ||var_r.nombreFuncion;
        RAISE NOTICE '%', functionDef;
        EXECUTE functionDef;
        RETURN NEXT;
    END LOOP;


END 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;

ALTER FUNCTION public.f_deleteAllFunctions()
  OWNER TO postgres;

select * from f_deleteAllFunctions();