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

发布于 2024-12-18 10:44:47 字数 825 浏览 3 评论 0原文

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

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);

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

有什么想法吗?

I'm trying to write a command that will delete all functions in a namespace. I've already found a command that will generate the drop functions script:

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;

Source: http://www.postgresonline.com/journal/archives/74-How-to-delete-many-functions.html

This will generate something like:

                 ?column?                 
------------------------------------------
 DROP FUNCTION public.function1(bigint);
 DROP FUNCTION public.function2();
 DROP FUNCTION public.function3(text);

However, I can't figure out how to change the code, so that the functions are actually deleted - as opposed to only generating the commands.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无人问我粥可暖 2024-12-25 10:44:47

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 函数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;
  • 如果任何涉及的函数存在依赖关系,则此操作会失败。可以通过添加 CASCADE 来解决,但我在这里没有这样做,因为它使函数更加危险。

相关:

The system catalogs changed in Postgres 11! (prokind instead of proisagg) See:


Could look like this:

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;

Call to show:

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

Call to delete:

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

Major points

  • You need dynamic SQL for that. Use a plpgsql function or a DO statement (PostgreSQL 9.0+) with EXECUTE.

  • Note the use of the functions pg_get_function_identity_arguments() and pg_function_is_visible. The latter can be omitted. It's a safeguard so you don't delete functions outside of the current user's search_path.

  • I added a "safe mode". Only delete if $2 = 'del'. Else only show generated SQL.

  • Be aware that the function will delete itself if it lives in the schema you delete from.

  • I also added quote_ident() to safeguard against SQLi. Consider the following:

CREATE FUNCTION "; DELETE FROM users;"()
  RETURNS int AS
'SELECT 1'
  LANGUAGE sql;
  • This fails if there are dependencies on any involved function. May be resolved by adding CASCADE, but I did not do that here, since it makes the function more dangerous, yet.

Related:

亚希 2024-12-25 10:44:47

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

Just COPY+PASTE the output of your query, into your psql interpreter. It will run all commands you paste.

沙沙粒小 2024-12-25 10:44:47

对于生成一组命令的任何 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;

For any SQL expression that generates a set of commands:

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;
笑看君怀她人 2024-12-25 10:44:47

我的版本没有存储过程

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$;

My Version without a stored procedure

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$;
凉风有信 2024-12-25 10:44:47
-- 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();
-- 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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文