Answer a question

Recently I needed to move objects from PostgreSQL's default schema "public" to another schema. I found this post which shows how to move tables which was great, but I also need to move the functions.

Answers

You could refine the loop some more (demonstrating only the second query):

DO
$do$
DECLARE
    r   record;
    sql text = '';
BEGIN
    FOR r IN
        SELECT p.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 := sql
          || format(E'\nALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'
                   ,r.proname, r.params);
    END LOOP;

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

Major points

  • Assignment operator in plpgsql is :=. = works, but is undocumented.

  • Remove unneeded tables from FROM.

  • concat() may be overkill, but format() simplifies the syntax.

Better set-based alternative

Re-casting the problem as set-based operation is more effective. One SELECT with string_agg() does the job:

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

PostgreSQL社区为您提供最前沿的新闻资讯和知识内容

更多推荐