将大型 PostgreSQL 表复制到行数有限的多个 csv 文件

BFl*_*lat 2 postgresql csv

有没有办法使用 sql 函数或现有的 psql 函数将非常大的表复制到多个 csv 文件中并指定输出文件中允许的最大行数?

例如,一个 3500 万行的表将输出 35 个 100 万行的 csv 文件。

Dan*_*ité 5

如果记录在文本字段中没有嵌入换行符,则存在严格的[一行 = 一条记录]映射,您可以将\copy csvin psql 的输出传递给 Unix 命令split。例如:

\copy (your query here) TO program 'split --lines 1000000' (format csv)
Run Code Online (Sandbox Code Playgroud)

请参阅 的选项split来更改输出文件或目标目录的名称格式。COPY如果您是超级用户,它也可以在服务器端使用\copy

如果记录可能嵌入了换行符,则情况会更复杂,因为使用上述方法,一条记录可能跨越两个连续的文件,使每个文件单独成为无效的 CSV 文件。例如:

\copy (select E'1st line\n2nd line') TO program 'split --lines 1' (format csv)
Run Code Online (Sandbox Code Playgroud)

会产生两个文件

xaa: "1st line
Run Code Online (Sandbox Code Playgroud)

xab: 2nd line"
Run Code Online (Sandbox Code Playgroud)

如果目标是将文件连接回单个文件来处理它,那么这并不重要,但如果必须单独处理它们,则应考虑不同的方法。

在 psql 中是可能的,但有点复杂(而不是用编程语言编写它)。从 PostgreSQL 12 开始,csv 是 psql 中的本机输出格式,因此查询上的游标可以与FETCH 1000000执行实际剪切和检索的语句一起使用。一段应该有效的脚本的框架如下所示:

\pset format csv
\pset tuples_only on
begin;
declare c cursor for your-query-here;
fetch 1000000  from c \g file1.csv
fetch 1000000  from c \g file2.csv
... as many times as necessary...
close c;
end;
Run Code Online (Sandbox Code Playgroud)

因为 psql 中没有循环构造,并且假设您事先不知道需要多少个获取步骤,所以您必须在上一步中生成该脚本片段,用于计算count(*)结果集并向编号文件发出(count(*)+NR-1)/NRtimes命令,例如fetch NR from...上面,其中NR是每个文件的记录数。