Exportieren Sie die Postgres-Tabelle als json

35

Gibt es eine Möglichkeit, Postgres-Tabellendaten als JSON in eine Datei zu exportieren? Ich brauche die Ausgabe Zeile für Zeile, wie:

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

BEARBEITEN: postgres version: 9.3.4

AliBZ
quelle

Antworten:

48

Versuchen Sie hier ein grundlegendes Intro zu PostgreSQLund JSON.

Außerdem ist die PostgreSQL-Dokumentation ziemlich gut. Probieren Sie sie hier aus . Überprüfen Sie die pretty_boolOption.

Ihre ursprüngliche Frage lautete "Gibt es eine Möglichkeit, Postgres-Tabellendaten zu exportieren als JSON". Sie wollten es in diesem Format

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

Ich hatte keine laufende Instanz von, PostgreSQLalso habe ich 9.4 heruntergeladen, kompiliert und installiert.

Um das zu beantworten, habe ich zuerst CREATEeinen Tisch bearbeitet (Fred)

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');

Dann, um zu überprüfen:

test=# select * from fred;

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

Dann habe ich diesen Befehl gegeben

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

Ich habe dann psql beendet und die Datei myfile aufgelistet.

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]$

(Sie können mit der Ausgabe von experimentieren

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

in Ihrer Freizeit).

@ Offby1 hat darauf hingewiesen, dass die Ausgabe (obwohl sie der Frage des OP entspricht) nicht korrekt ist JSON. @EvanCarroll wies darauf hin, dass dies \oauch eine Möglichkeit zur Ausgabe in eine Datei ist. Daher habe ich die Lösungen für diese beiden Probleme in dieser Anweisung kombiniert (mit Hilfe von hier ):

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

gibt:

[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]$ 

ENDLICH gibt es das Backslash ( \) - Problem, auf das @AdamGent in seinem Beitrag anspielt. Dies war ein bisschen schwierig, aber es ist möglich, ohne auf die Verarbeitung nach der Abfrage zurückzugreifen. Voilà:

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

Und mit REGEXP_REPLACE (beachte den cast :: TEXT) werden die überschüssigen Blackslashes entfernt.

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

gibt:

[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 Was den Kommentar von @ Zoltán angeht - das könnte eine Versionssache sein - nicht reproduzierbar!).

Vérace
quelle
2
Das scheint genau das zu sein, was das Originalplakat wollte. Beachten Sie jedoch, dass es sich bei jeder Zeile um JSON handelt, bei der Auflistung der Zeilen jedoch nicht, da die Zeilen nicht durch Kommas und eckige Klammern voneinander getrennt sind.
offby1
3
Dies wird NICHT funktionieren, wenn Sie irgendwelche backslashin Ihren Spalten haben !!!! Lesen Sie das COPY-Dokument sorgfältig durch, da es spezielle Aufgaben für backslashZeichen ausführt (z. B. das Hinzufügen eines weiteren Backslash).
Adam Gent
LESEN Sie @AdamGents Antwort unten, um das Backslash-Problem zu lösen
FacePalm
1
Also ... Jahr 2017 und KEINE MÖGLICHKEIT, JSON mit dem COPY-Befehl PostgreSQL zu EXPORTIEREN ?? Es gibt CSV-Option, TXT-Option ... Warum nicht eine JSON-Option?
Peter Krauss
1
Vielen Dank @ Vérace. Und sorry, jetzt habe ich ein COPY mit komplexem JSONb getestet und das verarbeitete JSON war in Ordnung, "richtiges JSON"!
Peter Krauss
13

Wenn Sie verwenden, psqlgibt es keinen Grund, \COPYüberhaupt zu verwenden.

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

Dies ist die gleiche Methode, die wir verwenden, um png / jpgs / tifs mit PostGIS aus der Datenbank zu holen, um sie schnell zu testen und um Skriptdateien mit PostgreSQL-Erweiterungen zu generieren.

Evan Carroll
quelle
Groß! Wie üblich COPY - Befehl „nicht relativen Pfad erlauben“ , die psqlist -native-Befehle der einfachste Weg , in relativen Pfad zu kopieren ! PS: Es gibt eine "Terminal-Methode", um einen echten COPY-Befehl mit einem relativen Pfad zu verwenden (siehe hier) . 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
6

Für mich @ verace Antwort hat die Spaltennamen nicht beibehalten, sondern zugewiesen Standardnamen ( f1, f2usw.) statt. Ich verwende PostgreSQL 9.1 mit der JSON-Erweiterung .

Wenn Sie die gesamte Tabelle exportieren möchten, ist keine Unterabfrage erforderlich. Darüber hinaus werden die Spaltennamen beibehalten. Ich habe die folgende Abfrage verwendet:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';
Zoltán
quelle
Spaltennamen wurden beibehalten! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));und das Ergebnis: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- Feldnamen sind mary, jimmy, paulie ... und NICHT ( f1, f2., etc) ...
verace
5

Ich werde Veraces Antwort eine besondere Einschränkung hinzufügen . Sie müssen Nachverarbeitung auf der ausgegebenen JSON - Datei tun , wenn Sie Textspalten mit Backslash Zeichen:\ .

Andernfalls erhalten Sie bestenfalls ein Duplikat ( \-> \\) und im schlimmsten Fall ein vollständig ungültiges JSON.

Dies:

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

Wird

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

Was gut aussieht, aber völlig ungültiges JSON ist.

Sie können das \\in \durch sed ersetzen :

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

Von Postgres COPY, wo sie es erwähnen:

Gegenwärtig gibt COPY TO niemals eine oktale oder hexadezimale Backslash-Sequenz aus, verwendet jedoch die anderen oben aufgeführten Sequenzen für diese Steuerzeichen. Jedes andere in der obigen Tabelle nicht erwähnte Zeichen mit umgekehrten Schrägstrichen wird als für sich selbst stehend angesehen. Beachten Sie jedoch, dass Sie keine unnötigen Backslashes hinzufügen, da dies versehentlich zu einer Zeichenfolge führen kann, die mit der Datenende-Markierung (.) Oder der Null-Zeichenfolge (standardmäßig \ N) übereinstimmt. Diese Zeichenfolgen werden erkannt, bevor eine andere Backslash-Verarbeitung durchgeführt wird.

Es wird dringend empfohlen, dass Anwendungen, die COPY-Daten generieren, Datenzeilen und Zeilenumbrüche in die Sequenzen \ n und \ r konvertieren. Gegenwärtig ist es möglich, einen Datenwagenrücklauf durch einen Backslash und einen Wagenrücklauf darzustellen und eine Daten-Newline durch einen Backslash und eine Newline darzustellen. Diese Darstellungen werden jedoch möglicherweise in zukünftigen Versionen nicht mehr akzeptiert. Sie sind auch sehr anfällig für Beschädigungen, wenn die COPY-Datei über verschiedene Computer übertragen wird (z. B. von Unix nach Windows oder umgekehrt).

COPY TO beendet jede Zeile mit einem Zeilenumbruch im Unix-Stil ("\ n"). Server, die unter Microsoft Windows ausgeführt werden, geben stattdessen Wagenrücklauf / Zeilenvorschub ("\ r \ n") aus, jedoch nur zum KOPIEREN in eine Serverdatei. Aus Gründen der Konsistenz über Plattformen hinweg sendet COPY TO STDOUT unabhängig von der Serverplattform immer "\ n". COPY FROM kann Zeilen verarbeiten, die mit Zeilenumbrüchen, Zeilenumbrüchen oder Zeilenumbrüchen / Zeilenumbrüchen enden. Um das Fehlerrisiko aufgrund von Zeilenumbrüchen oder Zeilenumbrüchen, die als Daten gedacht sind, zu verringern, beanstandet COPY FROM, wenn die Zeilenenden in der Eingabe nicht alle gleich sind.

Adam Gent
quelle
Ich habe mich in der Antwort mit diesem Thema befasst - ich hoffe, Sie finden es zufriedenstellend. Wenn nicht, lass es mich wissen.
9.
1

Eine allgemeine (MySQL, Postgres, SQLite ..) und kostenlose Lösung, für die Sie keine Software installieren müssen (außer Docker), finden Sie unter https://github.com/function61/sql2json

Vollständige Offenlegung: Ich habe diese Software geschrieben.

joonas.fi
quelle
0

Dies ist die einzige Methode, die gültiges JSON (Array of Objects) ausgibt .

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

( Quelle )

Gunar Gessner
quelle