PostgreSQL 10.12导出CSV行数远超原表的原因咨询
为什么PostgreSQL导出CSV的行数和原表不符?
这个问题我碰到过好几次!核心原因就是你那列XML字符串里藏着换行符(\n或者\r\n),CSV格式默认会把这些字符当成行分隔符,硬生生把一条记录拆成了好几条,所以行数直接炸到100多万。你换分隔符和引号的操作没触碰到根本问题——因为如果字段内的换行没被正确处理,不管用什么分隔符都会拆行。
具体原因拆解
- XML内容里的换行/回车符,在CSV导出时会被解析成新行的标志,哪怕你只选了一列,一条带换行的XML也会被拆成多行。
- 虽然CSV规范里规定,被引号包裹的字段内换行是允许的,但如果你的导出命令没明确要求强制用引号包裹所有字段,PostgreSQL可能不会自动包裹含特殊字符的字段,或者XML里本身有未转义的引号,导致包裹失效。
解决方案
这里给你三个靠谱的解决办法,按需选择:
1. 强制用引号包裹所有字段(推荐)
调整\copy命令,明确指定引号并强制所有字段都被包裹,这样XML里的换行和特殊字符会被正确转义,不会拆行:
\copy (select column from table) to 'directory/output.csv' with csv quote '"' force quote all;
这样导出后,每条XML都会被双引号完整包裹,内部的换行只会被视为字段内容的一部分,不会被当成新行。
2. 提前替换XML里的换行符
如果XML里的换行对你不重要,可以在导出前用replace函数把换行/回车符替换成空格或者其他符号:
\copy ( select replace(replace(column, '\n', ' '), '\r', '') from table ) to 'directory/output.csv' with csv;
这样导出的每条记录都是单行,行数就会和原表一致。
3. 换用text格式导出
如果不需要严格的CSV格式,可以用PostgreSQL的text格式,选一个XML里不会出现的分隔符(比如制表符):
\copy (select column from table) to 'directory/output.csv' with text delimiter E'\t';
制表符几乎不会出现在XML内容里,这样每条记录都会是完整的一行。
验证方法
导出后可以用wc -l directory/output.csv查看行数,或者把文件导回临时表验证计数:
CREATE TEMP TABLE temp_table (column_name text); \copy temp_table from 'directory/output.csv' with csv quote '"' force quote all; select count(*) from temp_table;
如果计数和原表的5万一致,就说明问题解决了。
内容的提问来源于stack exchange,提问作者Michael Johnson
相关产品推荐
相关产品推荐

