Postgresql PL/pgSQL从表中动态复制数据

Postgresql PL/pgSQL从表中动态复制数据,postgresql,plpgsql,postgresql-9.4,string-interpolation,Postgresql,Plpgsql,Postgresql 9.4,String Interpolation,我正在尝试编写一些SQL,以便根据信息模式中的内容从给定数据库中的所有PostgreSQL表复制数据。它应该将数据文件输出到我的本地计算机,以便导入到另一台计算机。最后,我将对此进行调整,以便只转储表的部分(我正在转储的一些表有数百万条记录,我只需要一小部分数据用于测试目的) 这是我到目前为止所拥有的 --Copy all tables... DO $$ DECLARE formatstring text; rec record; BEGIN RAISE NOTICE '

我正在尝试编写一些SQL,以便根据信息模式中的内容从给定数据库中的所有PostgreSQL表复制数据。它应该将数据文件输出到我的本地计算机,以便导入到另一台计算机。最后,我将对此进行调整,以便只转储表的部分(我正在转储的一些表有数百万条记录,我只需要一小部分数据用于测试目的)

这是我到目前为止所拥有的

--Copy all tables...
DO
$$
DECLARE
    formatstring text;
    rec record;
BEGIN
    RAISE NOTICE 'Copying tables...';
    formatstring = 'COPY (select * from %I) to ''C:\Media\Code\%s.csv'';';
    FOR rec IN 
        select table_name from information_schema.tables where table_schema = 'public' order by table_name
    LOOP
        RAISE NOTICE 'Table: %', rec.table_name;
        RAISE NOTICE format(formatstring, rec.table_name, rec.table_name);
        EXECUTE format(formatstring, rec.table_name, rec.table_name);
    END LOOP;
END;
$$
LANGUAGE plpgsql;
然而,我得到了这个例外

单引号的转义似乎很好(已经检查了这个问题:)。事实上,我可以执行以下操作,并在格式中插入文本:

select format('COPY (select * from %I) to ''C:\Media\Code\%s.csv'';', 'system_user', 'system_user');

有人能帮助解决这个问题吗?我可以很容易地编写一个脚本或代码来为我生成复制命令,但如果能在一个简单的SQL语句中完成这一切,那就太好了。

原因是您的3nd
RAISE
语句中存在语法错误。有,但不能直接将表达式馈送到
RAISE
。它必须是字符串文字-带有字符串插值选项

在做这件事的同时,我也会简化一些其他事情:

DO
$do$
DECLARE
   _formatstring text := $$COPY %1$I TO 'C:\Media\Code\%1$s.csv'$$;
   _sql text;
   _tbl text;
BEGIN
   RAISE NOTICE 'Copying tables...';
   FOR _tbl IN 
      SELECT table_name
      FROM   information_schema.tables
      WHERE  table_schema = 'public'
      ORDER  BY table_name
   LOOP
      _sql := format(_formatstring, _tbl);
      RAISE NOTICE 'Table: %', _tbl;
      RAISE NOTICE '%', _sql;  -- fixed!!
      EXECUTE _sql;
   END LOOP;
END
$do$ LANGUAGE plpgsql;
要点
  • 使用而不是
    的普通表名从tbl
    中选择*
  • 嵌套的使用
  • 格式说明符函数,所以我们只需要提供一次表名
  • 您可以在声明时分配变量
  • 标量变量,而不是
    FOR
    循环中的
    记录
    ——我们只需要一列

很难得也很愉快地看到这样一个问题:所有的基本信息和最少的噪音都清晰地呈现出来。起首部分!回答得很好。非常感谢你的帮助。我还有两个额外的问题:我想在输出文件名中包含table_目录,并且我想基于条件语句将某些表限制为特定的数据范围,而不是整个表,仅限于某些表。或者为了更好地解释,我想复制所有记录有限的静态数据表,但我只想从较大的表中复制一部分数据。不过,我可以自己调查一下,或者问另一个问题。非常感谢你的帮助:)@ManoDestra:是的,这听起来像是另一个问题。评论太多了。您始终可以链接到此链接以了解上下文。
DO
$do$
DECLARE
   _formatstring text := $$COPY %1$I TO 'C:\Media\Code\%1$s.csv'$$;
   _sql text;
   _tbl text;
BEGIN
   RAISE NOTICE 'Copying tables...';
   FOR _tbl IN 
      SELECT table_name
      FROM   information_schema.tables
      WHERE  table_schema = 'public'
      ORDER  BY table_name
   LOOP
      _sql := format(_formatstring, _tbl);
      RAISE NOTICE 'Table: %', _tbl;
      RAISE NOTICE '%', _sql;  -- fixed!!
      EXECUTE _sql;
   END LOOP;
END
$do$ LANGUAGE plpgsql;