我正在处理一些SEC 数据,这些数据在非常规则格式的制表符分隔文件中可用。
在 MySQL 上,我可以这样导入这些文件:
CREATE TABLE import ( adsh text, tag text, version text, ddate text, qtrs text, uom text, dimh text, iprx text, value text, footnote text, footlen text, dimn text, coreg text, durp text, datp text, dcml text);
LOAD DATA INFILE '/pg/import/2011/Q2/num.tsv' INTO TABLE import FIELDS ESCAPED BY '' IGNORE 1 ROWS;
这适用于每个文件。但是,在 Pg 服务器上运行的类似命令不起作用。在这种情况下,我使用该页面上 .zip 中的 2011 年第二季度“num”数据。此文件是一个 40 列的制表符分隔文件。我在 Pg 服务器上运行这个命令。
COPY import._2011_q2_num from '/pg/import/2011/Q2/num.tsv' DELIMITER E'\t' CSV HEADER;
ERROR: unterminated CSV quoted field
CONTEXT: COPY _2011_q2_num, line 830954: "0001193125-11-104388 DerivativeInstrumentsGainLossReclassifiedFromAccumulatedOCIIntoIncomeEffectiveP..."
根据 wc -l,该文件中有 830953 行。如果我删除最后一行,错误仍然存在 - 它只是说它像 830953 一样打开,等等。
我认为问题在于文件中出现了多个空字段:
\t\t\t\t
(来自 od -c)。我认为 Pg 正在将那些连续的标签视为转义。文档说:
ESCAPE...默认值与 QUOTE 值相同(这样如果引用字符出现在数据中,则加倍)。这必须是一个单字节字符。
好的,所以我必须为 ESCAPE 赋予一些价值,即使在这些文件中什么都不会被转义。文件中没有 \b ,所以我尝试了:
COPY import._2011_q2_num from '/pg/import/2011/Q2/num.tsv' DELIMITER E'\t' ESCAPE E'\b' CSV HEADER;
但是,我得到了同样的错误。
\b 也许有些时髦?我还尝试了波浪号(它出现在某些文件中,但我尝试了一个没有它的文件)和同样的错误。
-- with E for ESCAPE byte
copy import._2011_q2_num from '/pg/import/2011/Q2/num.tsv' ESCAPE E'~' DELIMITER E'\t' CSV HEADER
-- without E
copy import._2011_q2_num from '/pg/import/2011/Q2/num.tsv' ESCAPE '~' DELIMITER E'\t' CSV HEADER
根据我的测试,大约四分之一的文件失败,其余的成功。每个文件中有数百万行,因此手动检查它们是不切实际的,而且我不认为这些文件的构造很糟糕,因为 MySQL 没有问题。我想我只是没有给出正确的 Pg 语法 - ?
这是 Debian 11.3 上的 PostgreSQL 13.5
根据错误消息,您的内容
"
在字段中包含字符。在 CSV 中,这是允许的,但仅限于用引号括起来的字段(
"
默认情况下),并且字段内的引号被转义(默认情况下带有另一个引号)。如果未包含这些字段,则会收到问题中提到的错误。要借助内容中不存在的字符来解决该问题,请使用
QUOTE
选项(不要使用ESCAPE
)。通过设置QUOTE
为 以外的其他内容"
,"
则将成为普通字符,这只是基本 TSV 文件所需要的。