Tim*_*ith 5 postgresql csv postgresql-9.5
我有一个很大的制表符分隔文件,我想将其读入 PostgreSQL 9.5 中的表。 它包含双引号和反斜杠,我想将它们视为常规字符。
我认为 COPY FROM 是要走的路,但我不知道如何禁用转义。
以下是数据示例(来自Google 的 ngram 数据集):
aX13_X 2006 8 5
aX13_X 2007 4 3
aX13_X 2008 2 1
a\ 1852 1 1
a\ 1935 1 1
a\ 1937 2 2
ACT1V1T1ES 2003 15 11
ACT1V1T1ES 2004 63 6
ACT1V1T1ES 2005 1 1
ACT1V1T1ES 2006 5 4
ACT1V1T1ES 2008 4 3
ACTION=" 1995 3 3
ACTION=" 1996 6 5
ACTION=" 1997 9 7
ACTION=" 1998 19 11
ACTION=" 1999 11 5
Run Code Online (Sandbox Code Playgroud)
和表:
CREATE TABLE onegram (
id SERIAL,
ngram character text,
year integer NOT NULL,
match_count integer NOT NULL,
volume_count integer NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
如果我尝试不使用修饰符,反斜杠会转义选项卡:
ngram=# copy onegram (ngram, year, match_count, volume_count)
from '/home/tims/data/ngram/test.tsv';
ERROR: missing data for column "volume_count"
CONTEXT: COPY onegram, line 4: "a\ 1852 1 1"
Run Code Online (Sandbox Code Playgroud)
所以我切换到 CSV,然后双引号字符引用制表符:
ngram=# copy onegram (ngram, year, match_count, volume_count)
from '/home/tims/data/ngram/test.tsv' WITH CSV DELIMITER E'\t';
ERROR: unterminated CSV quoted field
CONTEXT: COPY onegram, line 17: "ACTION=" 1999 11 5
"
Run Code Online (Sandbox Code Playgroud)
使用 CSV 可以让我使用 DELIMITER 关键字。如果我选择样本中没有出现的分隔符(在这种情况下为空格),它会起作用:
ngram=# copy onegram (ngram, year, match_count, volume_count)
from '/home/tims/data/ngram/test.tsv' WITH CSV DELIMITER E'\t' QUOTE E' ';
COPY 16
Run Code Online (Sandbox Code Playgroud)
但我希望能够包含任何字符(制表符和换行符除外)。 那么,如何禁用 QUOTE?或者我可以用什么来代替 COPY FROM?
编辑:出于稍微随意的原因,理想情况下我想要一个不涉及预处理数据的选项。
该copy命令默认使用text带tab分隔符的格式。所以你只需要做一件事就是逃避反斜杠:
copy onegram (ngram, year, match_count, volume_count)
from program 'sed ''s/\\/\\\\/g'' < /home/tims/data/ngram/test.tsv';
select * from onegram;
???????????????????????????????????????????????????????
? id ? ngram ? year ? match_count ? volume_count ?
???????????????????????????????????????????????????????
? 1 ? aX13_X ? 2006 ? 8 ? 5 ?
? 2 ? aX13_X ? 2007 ? 4 ? 3 ?
? 3 ? aX13_X ? 2008 ? 2 ? 1 ?
? 4 ? a\ ? 1852 ? 1 ? 1 ?
? 5 ? a\ ? 1935 ? 1 ? 1 ?
? 6 ? a\ ? 1937 ? 2 ? 2 ?
? 7 ? ACT1V1T1ES ? 2003 ? 15 ? 11 ?
? 8 ? ACT1V1T1ES ? 2004 ? 63 ? 6 ?
? 9 ? ACT1V1T1ES ? 2005 ? 1 ? 1 ?
? 10 ? ACT1V1T1ES ? 2006 ? 5 ? 4 ?
? 11 ? ACT1V1T1ES ? 2008 ? 4 ? 3 ?
? 12 ? ACTION=" ? 1995 ? 3 ? 3 ?
? 13 ? ACTION=" ? 1996 ? 6 ? 5 ?
? 14 ? ACTION=" ? 1997 ? 9 ? 7 ?
? 15 ? ACTION=" ? 1998 ? 19 ? 11 ?
? 16 ? ACTION=" ? 1999 ? 11 ? 5 ?
???????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
看来您需要预处理数据。COPY如果您想允许任何可能的输入,则无法摄取此数据。它不是有效的 CSV,也不遵循 postgres 类似 TSV 的本机 COPY 格式的规则。没有可以设置的选项QUOTE NONE或类似的东西。
我建议使用类似 perl/python 脚本来转换数据,您可以使用COPY ... FROM PROGRAM. 或者通过管道将数据传输到psql客户端输入,或者通过转换数据并通过客户端驱动程序(如DBD::Pg或 )直接将其提供给 Postgres psycopg2,这两种方法都COPY支持。
你总是可以提交一个 postgres 补丁,这样下一个人就可以更轻松地解决同样的问题。
| 归档时间: |
|
| 查看次数: |
9665 次 |
| 最近记录: |