ส่งออกตาราง Postgres เป็น json


34

มีวิธีการส่งออกข้อมูลตาราง postgres เป็น json ไปยังไฟล์หรือไม่? ฉันต้องการผลลัพธ์เป็นบรรทัดต่อบรรทัดเช่น:

{'id':1,'name':'David'}
{'id':2,'name':'James'}
...

แก้ไข: รุ่น postgres: 9.3.4

คำตอบ:


47

ลองที่นี่สำหรับบทนำพื้นฐานในการและPostgreSQLJSON

นอกจากนี้เอกสาร PostgreSQL สวยดีจึงพยายามมันนี่ ตรวจสอบpretty_boolตัวเลือก

คำถามเดิมของคุณคือ "มีวิธีการส่งออกข้อมูลตาราง postgres เป็นJSON" หรือไม่ คุณต้องการในรูปแบบนี้

{'id':1,'name':'David'}
{'id':2,'name':'James'}
...

ฉันไม่มีอินสแตนซ์ที่ใช้งานอยู่PostgreSQLดังนั้นฉันจึงดาวน์โหลดรวบรวมและติดตั้ง 9.4

ในการตอบคำถามนี้ฉันจะCREATEแก้ไขตารางก่อน

CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));

INSERT INTO fred VALUES (2,    43, 'asfasfasfd'      );
INSERT INTO fred VALUES (3,   435, 'ererere'         );
INSERT INTO fred VALUES (6, 43343, 'eresdfssfsfasfae');

จากนั้นตรวจสอบ:

test=# select * from fred;

 mary | jimmy |      paulie      
------+-------+------------------
    2 |    43 | asfasfasfd
    3 |   435 | ererere
    6 | 43343 | eresdfssfsfasfae

จากนั้นฉันก็ออกคำสั่งนี้

test=# COPY (SELECT ROW_TO_JSON(t) 
test(# FROM (SELECT * FROM fred) t) 
test-# TO '/paulstuff/sware/db/postgres/inst/myfile';
COPY 3
test=# 

จากนั้นฉันก็เลิก psql และแสดงไฟล์ myfile

test=# \q
[pol@polhost inst]$ more myfile 
{"mary":2,"jimmy":43,"paulie":"asfasfasfd"}
{"mary":3,"jimmy":435,"paulie":"ererere"}
{"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}
[pol@polhost inst]$

(คุณสามารถทดลองกับผลลัพธ์จาก

COPY (SELECT ROW_TO_JSON(t, TRUE)  -- <-- Note addition of "TRUE" here!

ในยามว่าง)

มันชี้ให้เห็นโดย @ offby1 ว่าการส่งออก (ในขณะที่สอดคล้องกับคำถามของ OP) JSONไม่ถูกต้อง @EvanCarroll ชี้ให้เห็นว่า\oเป็นวิธีการส่งออกไปยังไฟล์ดังนั้นฉันรวมโซลูชั่นที่สอง niggles ในคำสั่งนี้ (ด้วยความช่วยเหลือจากที่นี่ ):

test=# \o out.json
test=# SELECT array_to_json(array_agg(fred), FALSE) AS ok_json FROM fred;
                                     -- <-- "TRUE" here will produce plus
                                        ("+) signs in the output. "FALSE"
                                        is the default anyway.
test=# \o

ให้:

[pol@polhost inst]$ more out.json 
                                                                   ok_json                                                                    
----------------------------------------------------------------------------------------------------------------------------------------------
 [{"mary":2,"jimmy":43,"paulie":"asfasfasfd"},{"mary":3,"jimmy":435,"paulie":"ererere"},{"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}]
(1 row)
[pol@polhost inst]$ 

ในที่สุดก็มีปัญหาเครื่องหมายแบ็กสแลช ( \) ที่ถูกกล่าวถึงโดย @AdamGent ในโพสต์ของเขา นี่เป็นเรื่องยุ่งยากเล็กน้อย แต่ก็เป็นไปได้โดยไม่ต้องใช้วิธีการประมวลผลการสืบค้นภายหลัง voila:

INSERT INTO fred VALUES (35, 5, 'wrew\sdfsd');
INSERT INTO fred VALUES (3, 44545, '\sdfs\\\sfs\\gf');

และใช้ REGEXP_REPLACE ดังนั้น (หมายเหตุ cast :: TEXT) จะลบแบล็กสแลชส่วนเกินออก

test=# \o slash.json
test=# SELECT REGEXP_REPLACE(ROW_TO_JSON(t)::TEXT, '\\\\', '\\', 'g') 
test=# FROM (SELECT * FROM fred) AS t;  -- I found that using a CTE was helpful for legibility
test=# \o
test=# \q

ให้:

[pol@polhost inst]$ more slash.json 
                    regexp_replace                    
------------------------------------------------------
 {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}
 {"mary":3,"jimmy":435,"paulie":"ererere"}
 {"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}
 {"mary":35,"jimmy":5,"paulie":"wrew\sdfsd"}
 {"mary":3,"jimmy":44545,"paulie":"\sdfs\\\sfs\\gf"}
(5 rows)
[pol@polhost inst]$ 

(ps สำหรับความคิดเห็นของ @ Zoltán - นี่อาจเป็นสิ่งที่เป็นเวอร์ชั่น - ไม่สามารถทำซ้ำได้!)


2
ดูเหมือนว่าจะเป็นสิ่งที่โปสเตอร์ดั้งเดิมต้องการ อย่างไรก็ตามโปรดทราบว่าในขณะที่แต่ละแถวมี JSON ที่เหมาะสมการรวบรวมแถวไม่ได้เนื่องจากไม่มีเครื่องหมายจุลภาคคั่นแถวและวงเล็บเหลี่ยมล้อมรอบพวกเขา
offby1

3
สิ่งนี้จะไม่ทำงานหากคุณมีbackslashอยู่ในคอลัมน์ของคุณ !!!! อ่านเอกสาร COPY อย่างระมัดระวังเนื่องจากทำสิ่งพิเศษสำหรับbackslashตัวละคร (เช่นการเพิ่มแบ็กสแลชอีกอัน)
Adam Gent

อ่าน @AdamGent คำตอบด้านล่างเพื่อแก้ปัญหาแบ็กสแลช
FacePalm

1
ดังนั้น ... ปี 2017 และไม่ส่งออก JSONด้วยคำสั่ง COPY PostgreSQL ?? มีตัวเลือก CSV, ตัวเลือก TXT ... ทำไมไม่เลือกตัวเลือก JSON
Peter Krauss

1
ขอบคุณ @ Vérace และขออภัยตอนนี้ฉันทดสอบสำเนาด้วย JSONb ที่ซับซ้อนและ JSON ที่ดำเนินการได้ไม่ดี "JSON ที่เหมาะสม"!
Peter Krauss

12

หากคุณกำลังใช้งานpsqlอยู่ก็ไม่มีเหตุผลที่จะใช้งาน\COPYเลย

\t
\a
\o file.json
SELECT row_to_json(r) FROM my_table AS r;

นี่เป็นวิธีการเดียวกับที่เราใช้เพื่อรับ png / jpgs / tifs ออกจากฐานข้อมูลด้วย PostGIS สำหรับการทดสอบอย่างรวดเร็วและเพื่อสร้างไฟล์สคริปต์ที่มีส่วนขยาย PostgreSQL


ที่ดี! ในฐานะที่เป็นคำสั่งคัดลอกปกติ"ไม่อนุญาตให้ทางญาติ"ที่psqlพื้นเมืองคำสั่งเป็นวิธีที่ง่ายที่สุดในการคัดลอกลงในทางญาติ ! PS: มี "ทางสถานี" เพื่อใช้คำสั่งคัดลอกจริงกับทางญาติให้ดูที่นี่ psql -h remotehost -d remote_mydb -U myuser -c "COPY (SELECT '{\"x\":1,\"y\":[\"a\",2]}'::json AS r) TO STDOUT" > ./relative_path/file.csv
Peter Krauss

5

สำหรับผมคำตอบ @ Véraceไม่ได้รักษาชื่อคอลัมน์ แต่ชื่อเริ่มต้นที่ได้รับมอบหมาย ( f1, f2ฯลฯ ) แทน ฉันใช้ PostgreSQL 9.1 กับนามสกุล JSON

หากคุณต้องการส่งออกทั้งตารางไม่จำเป็นต้องมีแบบสอบถามย่อย นอกจากนี้จะรักษาชื่อคอลัมน์ ฉันใช้แบบสอบถาม folowing:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';

มันรักษาชื่อคอลัมน์! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));และผลที่ได้: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- ชื่อฟิลด์เป็นแมรี่จิมมี่พอลลี่ ... และไม่ ( f1, f2. ฯลฯ ) ...
Vérace

5

ฉันจะเพิ่มคำเตือนเป็นพิเศษเพื่อตอบ Verace ของ ที่คุณต้องทำในการประมวลผลการโพสต์บนไฟล์ JSON \ออกมาถ้าคุณมีคอลัมน์ข้อความด้วยตัวอักษรทับขวา:

มิฉะนั้นคุณจะได้รับสำเนา ( \-> \\) ที่ดีที่สุดและไม่ถูกต้องของ JSON ที่แย่กว่านั่นคือ:

นี้:

{ "f1" : "crap\""}.

กลายเป็น

{ "f1" : "crap\\""}.

ซึ่งดูดี แต่ JSON ไม่ถูกต้องอย่างสมบูรณ์

คุณสามารถเปลี่ยน\\เข้า\กับ sed:

sed -i -e 's/\\\\/\\/g' PG_OUT_JSON_FILE.json

จากPostgres COPYที่พวกเขาพูดถึงมัน:

ปัจจุบัน COPY TO จะไม่ส่งลำดับแบ็กสแลชฐานแปดหรือฐานสิบหก แต่จะใช้ลำดับอื่น ๆ ที่แสดงไว้ด้านบนสำหรับอักขระควบคุมเหล่านั้น อักขระเครื่องหมายทับขวาอื่น ๆ ที่ไม่ได้กล่าวถึงในตารางข้างต้นจะถูกนำไปใช้เพื่อเป็นตัวแทนของตัวเอง อย่างไรก็ตามระวังการเพิ่มแบ็กสแลชโดยไม่จำเป็นเนื่องจากอาจทำให้เกิดสตริงที่ตรงกับเครื่องหมายสิ้นสุดของข้อมูล (.) หรือสตริง null (โดยค่าเริ่มต้น) โดยไม่ตั้งใจ สตริงเหล่านี้จะได้รับการยอมรับก่อนที่จะทำการประมวลผลแบ็กสแลชอื่น ๆ

ขอแนะนำอย่างยิ่งว่าแอปพลิเคชันที่สร้างข้อมูล COPY จะแปลงข้อมูลบรรทัดใหม่และการขึ้นบรรทัดใหม่เป็นลำดับ \ n และ \ r ตามลำดับ ในปัจจุบันมีความเป็นไปได้ที่จะเป็นตัวแทนของการรับคืนข้อมูลด้วยแบ็กสแลชและการคืนสินค้าและเพื่อแสดงบรรทัดข้อมูลใหม่ด้วยแบ็กสแลชและขึ้นบรรทัดใหม่ อย่างไรก็ตามการรับรองเหล่านี้อาจไม่ได้รับการยอมรับในรุ่นอนาคต นอกจากนี้ยังมีความเสี่ยงสูงที่จะเกิดความเสียหายหากไฟล์ COPY ถูกถ่ายโอนไปยังเครื่องอื่น (เช่นจาก Unix ไปยัง Windows หรือในทางกลับกัน)

COPY TO จะยกเลิกแต่ละแถวด้วยบรรทัดใหม่ของ Unix ("\ n") เซิร์ฟเวอร์ที่ทำงานบน Microsoft Windows แทนการส่งคืนการขึ้นบรรทัดใหม่ / ขึ้นบรรทัดใหม่ ("\ r \ n") แต่จะคัดลอกไปยังไฟล์เซิร์ฟเวอร์เท่านั้น เพื่อความสอดคล้องข้ามแพลตฟอร์ม COPY TO STDOUT จะส่ง "\ n" เสมอโดยไม่คำนึงถึงแพลตฟอร์มเซิร์ฟเวอร์ คัดลอกจากสามารถจัดการบรรทัดที่ลงท้ายด้วยการขึ้นบรรทัดใหม่การขึ้นบรรทัดใหม่หรือการขึ้นบรรทัดใหม่ / ขึ้นบรรทัดใหม่ เพื่อลดความเสี่ยงของข้อผิดพลาดอันเนื่องมาจากการขึ้นบรรทัดใหม่ที่ไม่มีเครื่องหมายแบ็กสแลชหรือการขึ้นบรรทัดใหม่ซึ่งมีความหมายเป็นข้อมูล COPY FROM จะบ่นหากว่าการจบบรรทัดในอินพุตนั้นไม่เหมือนกันทั้งหมด


ฉันได้จัดการกับคำตอบนี้ - ฉันหวังว่าคุณจะพอใจ ถ้าไม่บอกให้ฉันรู้
Vérace

1

สำหรับโซลูชันทั่วไป (MySQL, Postgres, SQLite .. ) และฟรีที่คุณไม่ต้องติดตั้งซอฟต์แวร์ใด ๆ (ยกเว้น Docker) โปรดดูที่https://github.com/function61/sql2json

การเปิดเผยแบบเต็ม: ฉันเขียนซอฟต์แวร์นั้น


0

นี่เป็นวิธีการเดียวที่ส่งออกJSON ที่ถูกต้อง (อาร์เรย์ของวัตถุ)

\t
\a
\o data.json
select json_agg(t) FROM (SELECT * from table) t;

(ที่มา )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.