Postgres COPY命令会转义新行和制表符

时间:2015-04-13 05:32:44

标签: postgresql function

我有一个sql函数:

CREATE OR REPLACE FUNCTION dump_func()
  RETURNS void AS
$BODY$
DECLARE

r  record;

loc varchar(100);

BEGIN

    for r in (SELECT f.oid as oid, proname, pg_get_functiondef(f.oid) as src
            FROM pg_catalog.pg_proc f
            INNER JOIN pg_catalog.pg_namespace n ON (f.pronamespace = n.oid)
            WHERE n.nspname = 'public') loop

        loc = '/Users/raman/Desktop/functions/' || r.proname || '.sql';

        raise notice '% - %', r.oid, loc;
        raise notice 'func: %', r.src;

         EXECUTE format('COPY (
            SELECT pg_get_functiondef(f.oid)
                FROM pg_catalog.pg_proc f
                INNER JOIN pg_catalog.pg_namespace n ON (f.pronamespace = n.oid)
            WHERE n.nspname = ''public'' and f.oid=%s
            ) TO ''%s'' ', r.oid, loc); 

    end loop;
end
$BODY$
  LANGUAGE plpgsql;

使用COPY命令将postgres中的每个db函数导出到一个单独的文件中。一切正常,除了在导出的sql文件中新的行和制表符被转义,例如:

  

创建或替换函数public.is_numeric(text)\ n RETURNS boolean \ n   LANGUAGE plpgsql \ n IMMUTABLE \ nAS $ function $ \ nDECLARE x   NUMERIC; \ n \ nBEGIN \ n x = $ 1 :: NUMERIC; \ n返回TRUE; \ n \ nEXEXCEPTION   当其他人返回错误时; \ nEND; \ n $ function $ \ n

正如您可以看到新的行和标签被转义,如何解决?

2 个答案:

答案 0 :(得分:0)

实际上,这可以做到。 Hacky虽然只是使用regexp_split_to_table并在\n字符上拆分。我只想自己解决同样的问题。这是我编写的代码:

DO $$

  DECLARE
    v_row record;
    v_proname text;
    v_sql text;

BEGIN

  FOR v_row IN (
    SELECT f.proname
    FROM pg_catalog.pg_proc AS f
    INNER JOIN pg_catalog.pg_namespace AS n ON (f.pronamespace = n.oid)
    WHERE n.nspname = 'public' AND f.proisagg = false
  ) LOOP

    SELECT v_row.proname::text INTO v_proname;
    EXECUTE FORMAT('COPY (
      SELECT regexp_split_to_table(regexp_replace(pg_get_functiondef(oid), ''\t'', ''   '', ''g''), ''\n'')
      FROM pg_catalog.pg_proc WHERE proname = ''%s'')
      TO ''C:\pg\%s.sql'';'
      , v_proname, v_proname);

  END LOOP;

END $$

答案 1 :(得分:0)

安德鲁的答案是正确的,也帮助我设置了格式。

我想出了一个类似的功能,但是要在PSQL中打印所有用户定义的功能。希望它对需要它的人有所帮助:

CREATE OR REPLACE FUNCTION printFunctions(stage VARCHAR, ischema VARCHAR, file_path VARCHAR)
  RETURNS VARCHAR AS
$$
DECLARE
  func VARCHAR;
  file_location TEXT;
BEGIN
  FOR func IN SELECT procname FROM listfunctions()
    LOOP
    SELECT (file_path || '/' || func || '_' || stage || '.sql') INTO file_location;
    IF (SELECT regexp_matches(func, '(pldb|plpg)')) IS NULL
      THEN
        EXECUTE 'COPY ' ||
                '(SELECT regexp_split_to_table(regexp_replace(pg_get_functiondef(oid), ''\t'', ''   '', ''g''),''\n'') from pg_proc where proname=' ||
                '''' || func || '''' ||
                ' and pronamespace=(select oid from pg_namespace where nspname=' ||
                '''' || ischema || ''''
                ')) TO ' || '''' || file_location || '''';
    END IF;
  END LOOP;
  RETURN stage;
END
$$
LANGUAGE 'plpgsql';

您可以通过以下方式调用它:

SELECT * FROM printFunctions('dev', 'public', '/tmp');