Function 在一次操作中更改多个PostgreSQL函数的架构?

Function 在一次操作中更改多个PostgreSQL函数的架构?,function,postgresql,schema,dynamic-sql,ddl,Function,Postgresql,Schema,Dynamic Sql,Ddl,最近,我需要将对象从PostgreSQL的默认模式“public”移动到另一个模式。我找到了一篇展示如何移动表的帖子,这很好,但我还需要移动函数。您可以进一步细化循环(仅演示第二个查询): DO$$ DECLARE row record; BEGIN FOR row IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' -- and other conditions, if needed LOOP

最近,我需要将对象从PostgreSQL的默认模式“public”移动到另一个模式。我找到了一篇展示如何移动表的帖子,这很好,但我还需要移动函数。

您可以进一步细化循环(仅演示第二个查询):

DO$$
DECLARE
    row record;
BEGIN
    FOR row IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' -- and other conditions, if needed
    LOOP
        EXECUTE 'ALTER TABLE public.' || quote_ident(row.tablename) || ' SET SCHEMA [new_schema];';
    END LOOP;
END;
$$;

DO$$
DECLARE
    row record;
    sql text = E'\n';
BEGIN
    FOR row IN
        SELECT
               proname::text as proname,
               pg_get_function_identity_arguments(p.oid) AS params
        FROM pg_proc p
        JOIN pg_namespace n on n.oid = p.pronamespace
        WHERE nspname = 'public'
     -- and other conditions, if needed
    LOOP
        sql = CONCAT(sql, E'\n',
            'ALTER FUNCTION public.', row.proname,
            '(', row.params, ') SET SCHEMA [new_schema];');
    END LOOP;
    RAISE NOTICE '%', sql; -- for viewing the sql before executing it
    -- EXECUTE sql; -- for executing the sql
END;$$;
要点
  • plpgsql中的赋值运算符是
    :=
    <代码>=有效,但未记录

  • 从中删除不需要的表

  • concat()
    可能有些过分,但是
    format()
    简化了语法

更好的基于集合的替代方案 将问题重新转换为基于集合的操作更有效。使用
string\u agg()
进行选择的一个操作:

DO
$do$
DECLARE
   sql text;
BEGIN
   SELECT INTO sql
          string_agg(format('ALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'
                   ,p.proname, pg_get_function_identity_arguments(p.oid)), E'\n')
   FROM   pg_proc p
   JOIN   pg_namespace n ON n.oid = p.pronamespace
   WHERE  nspname = 'public';
      -- and other conditions, if needed

   RAISE NOTICE '%', sql; -- for viewing the sql before executing it
   -- EXECUTE sql; -- for executing the sql
END
$do$;

我认为这是最好的办法。如果其他人有更好的方法,我会很高兴将其标记为答案。哎呀,我忘了从该查询的另一个应用程序中删除那些无关的连接。使用format函数编写的方式看起来要好得多。从现在起,我将使用它。将_agg串入
sql
变量是一个非常好的主意。感谢ErwinBTW,+1提到使用一些有效但未被记录的东西——最好以记录的方式做事。
DO
$do$
DECLARE
   sql text;
BEGIN
   SELECT INTO sql
          string_agg(format('ALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'
                   ,p.proname, pg_get_function_identity_arguments(p.oid)), E'\n')
   FROM   pg_proc p
   JOIN   pg_namespace n ON n.oid = p.pronamespace
   WHERE  nspname = 'public';
      -- and other conditions, if needed

   RAISE NOTICE '%', sql; -- for viewing the sql before executing it
   -- EXECUTE sql; -- for executing the sql
END
$do$;