テーブルのデータを含むcsv
ファイルをpostgresにインポートしようとしています。テーブルの列の1つにjsonb
タイプがあります。
csv
ファイルの1行に次のようなものが含まれています
1,{"a":"b"}
テーブルにスキーマがあるとします
id | smallint |
data | jsonb |
データを挿入しようとすると、すべて正常に動作します
INSERT INTO table VALUES (1, '{"a":"b"}');
でファイルから直接インポートしようとしています
COPY table FROM '/path/to/file.csv' DELIMITER ',' csv;
次のエラーが表示されます。
ERROR: invalid input syntax for type json
DETAIL: Token "a" is invalid.
CONTEXT: JSON data, line 1: {a...
COPY availability, line 1, column services: "{a: b}"
フィールドを'
、"
、\"
および\'
で引用しようとしましたが、何も機能しません。
それを行う正しい構文はどれですか?
PostgreSQLのCOPY
コマンドはめったに理想的ではありませんが、しばしば機能します。参考までに、これを推測するよりも良い方法があります。
CREATE TEMP TABLE baz AS
SELECT 1::int, '{"a":"b"}'::jsonb;
これは正確なサンプルデータです。これで、さまざまな設定をテストできます。
# COPY baz TO STDOUT;
1 {"a": "b"}
COPY baz TO STDOUT DELIMITER ',';
1,{"a": "b"}
上記はあなたが質問した正確なデータを生成することがわかります...
COPY baz TO '/tmp/data.csv' DELIMITER ',';
問題はない。少なくともPostgreSQL 9.5ではできません。
だからあなたの問題はどこですか、それはCSVモードでです。観察する、
# COPY baz TO STDOUT;
1 {"a": "b"}
# COPY baz TO STDOUT CSV;
1,"{""a"": ""b""}"
これらの2つが異なることがわかります。上記のCSVモードで生成された形式を想定したCSVモードで非CSVファイルをロードしてみましょう。
TRUNCATE baz;
COPY baz FROM '/tmp/data.csv' DELIMITER ',' CSV;
ERROR: invalid input syntax for type json
DETAIL: Token "a" is invalid.
CONTEXT: JSON data, line 1: {a...
COPY baz, line 1, column jsonb: "{a: b}"
エラーになります。その理由は RFC 418 に由来します
各フィールドは二重引用符で囲まれている場合と囲まれていない場合があります(ただし、Microsoft Excelなどの一部のプログラムでは二重引用符がまったく使用されていません)。 フィールドが二重引用符で囲まれていない場合、フィールド内に二重引用符が表示されないことがあります。
この時点で2つのオプションがあります。
したがって、これらはCSVモードの同じオプションで有効な入力になります。
#COPY baz TO STDOUT DELIMITER ',' CSV ESCAPE E'\\';
1,"{\"a\": \"b\"}"
# COPY baz TO STDOUT DELIMITER ',' CSV;
1,"{""a"": ""b""}"
解決策を見つけた、postgresは"
エスケープ文字として、正しい形式にする必要があります
{"""a""": """b"""}
他の回答で述べたように、 CSV そしてその JSON 仕様(そしておそらく postgresql 仕様)は多少互換性がありません。少なくとも単純な形で彼らに戦いを止めさせるには、それらが判読不能な混乱になるまで物事を脱出する必要があります。使用していない CSV モードはさらに悪い コピー 何でも死ぬ JSON 埋め込まれた新しい行、バックスラッシュ、または引用符に問題があります。
もっと複雑な入力でのみ、まったく同じ問題が発生しました。 ENUM 型、整数、複素数 JSON 田畑。ウィットするには:
create table messages( a blab, b integer, c text, d json, e json);
典型的な場所 JSONsは{"default":"little","sms":"bigger"}
および["name","number"]
。それらの山をインポートしてみてください コピー コマンド:コンマが JSON 引用符を取得しないでください!私はこれを見つけるまで何時間も費やします この素晴らしいブログ投稿 これは問題の原因とそれから抜け出すために必要なオプションを指摘しました。
基本的には、区切り文字と引用符のフィールドを、あなたの中にないことを保証できるものに変更する必要があります JSON データ。私の場合、私はたくさんを保証できるので、私はただ行くことができます
COPY messages( a, b, c, d, e) from stdin csv quote '^' delimiter '|';
malfunction|5|La la la|{"default":"little","sms":"bigger"}|["name","number"]
見やすく、読みやすく、お気に入りのテキストマングラーのマイナーな文字置換で簡単にアクセスでき、何も逃げません。上記で使用されている文字があなたの中にないことを保証できない場合 JSON 次に、かなり風変わりなe'\x01'
およびe'\x02'
として JSON 仕様はそれらを完全に違法と見なします。読みやすさなどは劣りますが、正確には正確です。
一部のように、埋め込まれた改行に注意してください JSON ジェネレーターは読みやすさの目的で出力する傾向がありますが、それでも「いいえ」ではないので、あなたはそれらをあなたのフィルターから取り除く必要があります JSON。