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
そしてテーブル:
CREATE TABLE onegram (
id SERIAL,
ngram character text,
year integer NOT NULL,
match_count integer NOT NULL,
volume_count integer NOT NULL
);
修飾子なしで試すと、バックスラッシュがタブをエスケープします。
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"
だから私は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
"
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
しかし、任意の文字を含めることができるようにしたい(タブと改行を除く)。 では、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 ║
╚════╧════════════╧══════╧═════════════╧══════════════╝
データを前処理する必要があるようです。 COPY
は、可能な入力を許可する場合、このデータを取り込むことができません。これは有効なCSVではなく、postgresのTSVに似たネイティブCOPY形式のルールにも従いません。 QUOTE NONE
などを設定するオプションはありません。
COPY ... FROM PROGRAM
を使用して呼び出すデータを変換するPerl/pythonスクリプトのようなものをお勧めします。または、クライアント側の入力のためにデータをpsql
にパイプするか、データを変換してDBD::Pg
やpsycopg2
などのクライアントドライバーを介してPostgresに直接フィードします。 COPY
サポート。
いつでもpostgresパッチを提出して、次の人が同じ問題を簡単に解決できるようにすることができます。
@ Craig Ringerから、データを再フォーマットする必要があります。
あなたのデータに基づいて、Linuxでは、インポートする前にtr
&seq
を使用してCSVファイルをフォーマットしました。
例:a.csv
以下のファイル
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
CSVのフォーマット、引用符の無効化(複数のスペースを1つのスペースに置き換えてからスペース&\t
から;
)。 c.csv
は結果ファイルです。ただし、小さなデータでテストしたため、入力データが大きい場合は確認してください。
cat a.csv | tr -s " " > b.csv; sed -e 's/"//g' -e "s/[\t ]/;/g" b.csv > c.csv
cat c.csv
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
PGにインポート
psql -p 5432 -d postgres -c "copy onegram (ngram, year, match_count, volume_count) from '/opt/c.csv' DELIMITER ';' CSV"
インポート後、結果は次のようになります。
id | ngram | year | match_count | volume_count
----+------------+------+-------------+--------------
20 | aX13_X | 2006 | 8 | 5
21 | aX13_X | 2007 | 4 | 3
22 | aX13_X | 2008 | 2 | 1
23 | a\ | 1852 | 1 | 1
24 | a\ | 1935 | 1 | 1
25 | a\ | 1937 | 2 | 2
26 | ACT1V1T1ES | 2003 | 15 | 11
27 | ACT1V1T1ES | 2004 | 63 | 6
28 | ACT1V1T1ES | 2005 | 1 | 1
29 | ACT1V1T1ES | 2006 | 5 | 4
30 | ACT1V1T1ES | 2008 | 4 | 3
31 | ACTION= | 1995 | 3 | 3
32 | ACTION= | 1996 | 6 | 5
33 | ACTION= | 1997 | 9 | 7
34 | ACTION= | 1998 | 19 | 11
35 | ACTION= | 1999 | 11 | 5