有没有办法使用 sql 函数或现有的 psql 函数将非常大的表复制到多个 csv 文件中并指定输出文件中允许的最大行数?
例如,一个 3500 万行的表将输出 35 个 100 万行的 csv 文件。
如果记录在文本字段中没有嵌入换行符,则存在严格的[一行 = 一条记录]映射,您可以将\copy csv
in 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)/NR
times命令,例如fetch NR from...
上面,其中NR
是每个文件的记录数。
归档时间: |
|
查看次数: |
4457 次 |
最近记录: |