您可以根据列值将Postgres表导出为多个CSV文件吗?

Pau*_*aul 1 csv postgresql

我在Postgres有一个约6M行的表,想要拆分并将它们导出为多个CSV文件.有没有办法根据行列的值自动生成不同的CSV文件?

Cra*_*ger 7

一般来说,你想要的COPY (SELECT ...).

一种选择是使用PL/PgSQL和EXECUTE.就像是:

DO
LANGUAGE plpgsql
$$
DECLARE
    colval integer;
BEGIN
    FOR colval IN SELECT DISTINCT thecol FROM thetable
    LOOP
       EXECUTE format('COPY (SELECT * FROM thetable WHERE colval = %L) TO ''/tmp/out-%s.csv'';', colval, colval);
    END LOOP;
END;
$$
Run Code Online (Sandbox Code Playgroud)

另一种是使用psql和编写脚本\copy.

另一种方法是使用您首选的客户端语言及其支持COPY,例如PgJDBC的CopyManager,Python + psycopg2 copy_to等.

更新:我刚刚意识到它比这更简单.ORDER BY目标列,并在处理时拆分文件流.示例psql,bashawk:

CREATE TABLE demo(
  id serial primary key,
  targetcol integer not null
);

-- Create 10 distinct values for targetcol with 100 entries each
insert into demo(targetcol)
select x
from generate_series(1,10) x cross join generate_series(1,100) y;
Run Code Online (Sandbox Code Playgroud)

然后将$ 2列作为文件名的一部分,将文件切换为输出记录:

psql -At -c '\copy (SELECT * FROM demo ORDER BY targetcol) TO stdout' | \
awk '
  BEGIN {
    prev_col=0;
    cur_file="";
  } 
  {
    if ($2 != prev_col) {
      prev_col = $2;
      if (cur_file != "") {
        close(cur_file);
      }
      cur_file = sprintf("outfile-%d",$2);
      printf "" > cur_file;
    } 
    print $0 >> cur_file; 
  }
';
Run Code Online (Sandbox Code Playgroud)

事实上,如果您不介意它有点慢,并且如果目标列的值很多,可能会耗尽最大打开文件,这甚至不需要排序输入:

psql -At -c '\copy demo TO stdout' | \
awk '
  BEGIN {
    cur_file="";
  } 
  {
    print $0 >> sprintf("outfile-%d",$2); 
  }
';
Run Code Online (Sandbox Code Playgroud)


Gre*_*reg 6

当然有几种方法可以做到这一点。我想不出一种方法可以在单个命令中自动执行此操作。我不知道您的操作系统是什么,或者您是否想在存储过程中执行此操作,或者?如果我要从命令行快速而肮脏地执行此操作,我会:

$ # bash shell here.
$ for i in `psql -Upostgres -h HOSTIP -Atq DBNAME -c 'select distinct COLNAME from TABLENAME'`; do
$   echo 'working on ': $i
$   cmd="select * from TABLENAME where COLNAME = '$i'"
$   psql -Upostgres -h HOSTIP -Atq DBNAME -c "copy ( $cmd ) to stdout with delimiter ','" > /tmp/$i
$ done
Run Code Online (Sandbox Code Playgroud)

您将需要提供: HOSTIP(如果默认连接正确,则省略 -h HOSTIP) DBNAME 包含数据的数据库 TABLENAME 具有 6MM 行的表的名称 COLNAME 指示文件名称的列的名称将数据复制到

结果是 /tmp 目录中的一堆文件,其中包含表格内容的逗号分隔部分。

这应该会给你一些想法。我想你的问题的答案是否定的,没有“自动”的方式。祝你好运!

-G