2

最近我需要将对象从 PostgreSQL 的默认模式“公共”移动到另一个模式。我发现这篇文章展示了如何移动表格,这很棒,但我还需要移动这些功能。

4

2 回答 2

3

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

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

要点

  • plpgsql 中的赋值运算符是:=. =有效,但没有记录。

  • 从 中删除不需要的表FROM

  • concat()可能是矫枉过正,但format()简化了语法。

更好的基于集合的替代方案

将问题重铸为基于集合的操作更有效。一个 SELECT 可以string_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$;
于 2013-10-03T00:19:20.560 回答
0
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;$$;
于 2013-10-02T22:47:45.387 回答