Postgres tablosunu json olarak dışa aktar


34

Postgres tablo verilerini bir dosyaya json olarak dışa aktarmanın bir yolu var mı? Çıktının satır satır olması gerekir, şöyle:

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

EDIT: postgres versiyonu: 9.3.4

Yanıtlar:


47

Deneyin burada temel için tanıtımın PostgreSQLve JSON.

Ayrıca, PostgreSQL belgeleri oldukça iyidir, bu yüzden burada deneyin . Seçeneğe göz atın pretty_bool.

Asıl sorunuz "Postgres tablo verilerini şu şekilde dışa aktarmanın bir yolu var mı JSON" idi. Bu formatta istediniz

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

Çalışan bir örneğim yoktu, PostgreSQLbu yüzden indirdim, derledim ve yükledim 9.4.

Buna cevap vermek için önce CREATEbir masa hazırladım (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');

Ardından kontrol etmek için:

test=# select * from fred;

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

Sonra bu komutu verdim

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

Daha sonra psql'den çıktım ve dosyamı myfile'da listeledim.

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

(çıktı ile deneme yapabilirsiniz

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

müsait olduğunda).

@ Offby1 ile çıkışın (OP'nin sorusuna karşılık gelirken) doğru olmadığı belirtildi JSON. @EvanCarroll \o, bunun bir dosya çıktısı oluşturmanın da bir yolu olduğuna dikkat çekti , bu yüzden bu iki niggles'ın çözümlerini bu açıklamada birleştirdim ( buradan gelen yardımı ile ):

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

verir:

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

Nihayet , \@AdamGent'in görevinde bahsettiği backslash ( ) sorunu var. Bu biraz zor, ama bir post-sorgu işleme başvurmadan mümkün. Voilà:

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

Ve böylece REGEXP_REPLACE kullanarak (cast :: TEXT 'e bakın) fazlalık siyah noktaları giderir.

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

verir:

[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 'ın yorumuna gelince - bu sürüm bir şey olabilir - çoğalamıyor!).


2
Orijinal posterin istediği tam olarak bu gibi görünüyor. Bununla birlikte, her satırın uygun JSON olmasına rağmen, satırların toplanması , satırları birbirinden ayıran virgüllerden ve etraflarını saran köşeli parantezlerden yoksundur.
offby1

3
Bu olacak DEĞİL Eğer varsa çalışmak backslashsütunlarınızdaki !!!! COPY doc backslashkarakterlerini (başka bir ters eğik çizgi eklemek gibi) özel şeyler yaptığı için dikkatlice okuyun .
Adam Gent,

@AdamGent'in ters eğik çizgi sorununu çözmek için verdiği cevabı
OKUYUN

1
Yani ... yıl 2017 ve KOPYA komutu ile JSON'U İHRACAT YOK PostgreSQL ?? CSV seçeneği var, TXT seçeneği ... Neden bir JSON seçeneği değil?
Peter Krauss

1
@ Vérace'ye teşekkürler. Ve üzgünüm, şimdi karmaşık JSONb ile bir COPY test ettim ve işlem görmüş JSON iyi, "uygun JSON"!
Peter Krauss

12

Kullanıyorsanız kullanmak psqliçin hiçbir sebep yoktur \COPY.

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

Bu, hızlı testler için PostGIS ile veritabanından png / jpgs / tifs elde etmek ve PostgreSQL uzantılı komut dosyaları oluşturmak için kullandığımız yöntemdir.


Harika! Her zamanki KOPYA komutu olarak "göreli yolu izin" , psql-Anadili-komutlar ise göreli yol kopyalamak için en kolay yolu ! Not: Gerçek COPY komutunu göreceli yolla kullanmanın bir "terminal yolu" var, buraya bakın . 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

Benim için @ Verace cevabı sütun adlarını korumak yoktu, ama atanan varsayılan adları ( f1, f2vs.) yerine. JSON uzantılı PostgreSQL 9.1 kullanıyorum .

Tüm tabloyu dışa aktarmak istiyorsanız, alt sorguya gerek yoktur. Buna ek olarak, bu olacak sütun adlarını korumak. Aşağıdaki sorguyu kullandım:

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

Sütun isimlerini korudu! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));ve sonuç: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- alan adları mary jimmy, paulie ... ve vardır DEĞİL ( f1, f2., vb ...)
Verace

5

Verace'nin cevabına özel bir uyarı ekleyeceğim . Eğer ters eğik çizgi karakterleri ile metin sütunları varsa outputted JSON dosya üzerinde işlem gönder yapmanız gerekir:\ .

Aksi taktirde en iyisi olarak çoğaltılmış ( \-> \\) ve daha da kötüsü tamamen geçersiz JSON alacaksınız :

Bu:

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

Oluyor

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

Güzel görünüyor ama tamamen geçersiz JSON.

\\İçine \sed ile değiştirebilirsiniz :

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

Gönderen Postgres KOPYASINI onlar yuvarlak yaklaşık bundan söz burada:

Halen, COPY TO asla bir sekizli veya onaltılık basamak ters eğik çizgi dizisi yayamaz, ancak bu kontrol karakterleri için yukarıda listelenen diğer dizileri kullanır. Yukarıdaki tabloda belirtilmeyen diğer herhangi bir arkaya eğik karakter kendisini temsil etmek için alınacaktır. Bununla birlikte, gereksiz yere ters eğik çizgi eklemekten sakının, çünkü yanlışlıkla veri sonu işaretçisini (.) Veya boş dize (varsayılan olarak \ N) ile eşleşen bir dize oluşturabilir. Bu dizgiler, diğer ters eğik çizgi işlemlerinden önce tanınacaktır.

COPY veri üreten uygulamaların veri satırlarını ve satırbaşlarını sırasıyla \ n ve \ dizilerine dönüştürmeleri şiddetle tavsiye edilir. Şu anda bir veri satır başı ile ters eğik çizgi ve satır başı tarafından temsil etmek ve bir veri satır yolunu ters eğik çizgi ve satırsonu ile göstermek mümkündür. Ancak, bu beyanlar gelecek sürümlerde kabul edilmeyebilir. COPY dosyası farklı makineler arasında aktarılırsa (örneğin, Unix'ten Windows'a veya tersi), yolsuzluğa karşı da oldukça hassastırlar.

COPY TO, her satırı bir Unix tarzı yeni satırla ("\ n") sonlandırır. Microsoft Windows üzerinde çalışan sunucular bunun yerine satır başı / satırsonu ("\ r \ n") verir, ancak yalnızca bir sunucu dosyasına KOPYA için; Platformlar arasında tutarlılık için, COPY TO STDOUT, sunucu platformundan bağımsız olarak her zaman "\ n" gönderir. COPY FROM, yeni satırlar, satır başı veya satır başı / satırsonları ile biten satırları yönetebilir. Girintisiz satır sonları veya veri anlamına gelen satır başı satırları nedeniyle hata riskini azaltmak için, girdideki satır sonları birbirine benzemiyorsa, COPY FROM şikayetçi olacaktır.


Bu konuyu cevabında ele aldım - umarım tatmin edici bulursunuz. Eğer değilse, bana bildirin.
Vérace


0

Geçerli JSON (nesne dizisi) çıkaran tek yöntem budur .

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

( kaynak )

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.