PL / pgSQL çıktısını PostgreSQL'den bir CSV dosyasına kaydedin


Yanıtlar:


1367

Ortaya çıkan dosyayı sunucuda mı yoksa istemcide mi istiyorsunuz?

Sunucu tarafı

Yeniden kullanımı veya otomatikleştirilmesi kolay bir şey istiyorsanız, Postgresql'in yerleşik COPY komutunu kullanabilirsiniz. Örneğin

Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;

Bu yaklaşım tamamen uzak sunucuda çalışır - yerel bilgisayarınıza yazamaz. Ayrıca Postgres "süper kullanıcı" (normalde "root" olarak adlandırılır) olarak çalıştırılması gerekir, çünkü Postgres bu makinenin yerel dosya sistemiyle kötü şeyler yapmasını durduramaz.

Bu aslında bir süper kullanıcı olarak bağlanmak zorunda olduğunuz anlamına gelmez (farklı bir güvenlik riski olabilecek otomatikleştirme), çünkü bir süper kullanıcıymış gibi çalışan bir işlev yapmak için SECURITY DEFINERseçeneğiCREATE FUNCTION kullanabilirsiniz .

Önemli olan, fonksiyonunuzun sadece güvenliği atlamak için değil, ek kontroller yapmak için orada olmasıdır - böylece tam olarak ihtiyacınız olan verileri dışa aktaran bir fonksiyon yazabilir veya çeşitli seçenekleri kabul edebilecekleri bir şey yazabilirsiniz katı bir beyaz liste ile tanışın. İki şeyi kontrol etmeniz gerekir:

  1. Kullanıcının hangi dosyaları diskte okumasına / yazmasına izin verilmelidir? Bu örneğin belirli bir dizin olabilir ve dosya adının uygun bir önek veya uzantıya sahip olması gerekebilir.
  2. Kullanıcı veritabanında hangi tabloları okuyabilmeli / yazabilmelidir? Bu normalde GRANTveritabanındaki s tarafından tanımlanır , ancak işlev şimdi bir süper kullanıcı olarak çalışmaktadır, bu nedenle normalde "sınırların dışında" olacak tablolara tam olarak erişilebilir olacaktır. Muhtemelen birisinin işlevinizi çağırmasına ve "kullanıcılar" tablonuzun sonuna satır eklemesine izin vermek istemezsiniz ...

Sıkı koşulları karşılayan dosyaları ve tabloları dışa aktarma (veya içe aktarma) işlevlerinin bazı örnekleri de dahil olmak üzere , bu yaklaşımı genişleten bir blog yazısı yazdım .


Müşteri tarafı

Diğer yaklaşım, istemci tarafında , yani uygulamanızda veya komut dosyanızda dosya işlemeyi yapmaktır . Postgres sunucusunun hangi dosyayı kopyaladığınızı bilmesine gerek yoktur, sadece verileri tükürür ve istemci dosyayı bir yere koyar.

Bunun altında yatan sözdizimi COPY TO STDOUTkomuttur ve pgAdmin gibi grafik araçları sizin için güzel bir iletişim kutusunda sarar.

psqlKomut satırı istemcisi adı verilen özel bir "meta-komutu" vardır \copy"gerçek" aynı seçenekleri alır COPY, ancak istemci içinde çalıştırılır:

\copy (Select * From foo) To '/tmp/test.csv' With CSV

;SQL komutlarının aksine meta komutlar yeni satırla sonlandığından , sonlandırma olmadığını unutmayın .

Gönderen docs :

COPY'yi psql yönergesi \ copy ile karıştırmayın. \ copy STDIN'den COPY veya STDOUT'a COPY'yi çağırır ve ardından verileri psql istemcisinin erişebileceği bir dosyaya getirir / depolar. Bu nedenle, \ copy kullanıldığında dosya erişilebilirliği ve erişim hakları sunucuya değil istemciye bağlıdır.

Uygulama programlama dilinizin verileri itme veya alma desteği de olabilir , ancak giriş / çıkış akışını bağlamanın bir yolu olmadığından, COPY FROM STDIN/ TO STDOUTstandart bir SQL deyimi içinde / kullanamazsınız . PHP'nin PostgreSQL işleyicisi ( PDO değil ) çok büyük pg_copy_fromve pg_copy_tobir PHP dizisine kopyalanan ve büyük veri kümeleri için verimli olmayabilecek işlevleri içerir .


131
Açıkçası yukarıdaki örnek bazen kullanıcının bir süper kullanıcı olmasını gerektirir, sıradan insanlar için bir sürüm;) echo “KOPYA (foo'dan SELECT *) CSV HEADER ile STDOUT” | psql -o '/tmp/test.csv' veritabanı_adı
Drachenfels

10
@Drachenfels: da \copyçalışır - orada, yollar istemciye göredir ve noktalı virgül gerekmez. Düzenlememe bakın.
krlmlr

3
@ IMSoP: Bir sql (postgres 9.3) işlevine nasıl bir COPY deyimi eklersiniz? Sorgu bir .csv dosyasına kaydedilir?
JO.

12
Görünüşe \copygöre bir astar olmak gerekiyor. Böylece sql'i istediğiniz gibi biçimlendirmenin güzelliğini elde edemezsiniz ve sadece çevresine bir kopya / işlev koyabilirsiniz.
isaaclw

1
Cevap devletler olarak @AndreSilva, \copyözel bir meta-komut içinde psqlkomut satırı istemcisi . PgAdmin gibi diğer istemcilerde çalışmaz; muhtemelen bu işi yapmak için grafik sihirbazları gibi kendi araçlarına sahip olacaklar.
IMSoP

519

Birkaç çözüm var:

1 psqlkomut

psql -d dbname -t -A -F"," -c "select * from users" > output.csv

Bu, SSH aracılığıyla kullanabileceğiniz büyük bir avantaja sahiptir, örneğin ssh postgres@host command-

2 postgres copykomutu

COPY (SELECT * from users) To '/tmp/output.csv' With CSV;

3 psql etkileşimli (veya değil)

>psql dbname
psql>\f ','
psql>\a
psql>\o '/tmp/output.csv'
psql>SELECT * from users;
psql>\q

Hepsi komut dosyalarında kullanılabilir, ancak # 1'i tercih ederim.

4 pgadmin ama yazılabilir değil.


32
IMHO ilk seçenek hataya açıktır, çünkü dışa aktarılan verilerde virgülün uygun şekilde kaçmasını içermez.
Piohen

4
Ayrıca, psql hücre değerleri belirtmez, bu nedenle verilerinizden HERHANGİ sınırlayıcı kullanırsa dosyanız bozulur.
Cerin

7
@Cerin -t, --tuples-only ile eşanlamlıdır (sütun adlarının ve sonuç satır sayısı altbilgilerinin vb. Yazdırılmasını kapatın) - sütun başlıklarını almak için
atlayın

21
Sadece test virgülle kaçan iddia-bu doğru, metod 1. gelmez değil değerlerde virgül kaçmak.
MrColes

1
Ayrıca "\ pset footer" kullanın, böylece satır sayıları dosyada çapa yok
techbrownbags

94

Terminalde (db'ye bağlıyken) cvs dosyasına çıkış ayarlayın

1) Alan ayırıcıyı şu şekilde ayarlayın ',':

\f ','

2) Çıktı formatını hizasız olarak ayarlayın:

\a

3) sadece tuples göster:

\t

4) Set çıkışı:

\o '/tmp/yourOutputFile.csv'

5) Sorgunuzu yürütün:

:select * from YOUR_TABLE

6) Çıktı:

\o

Daha sonra, bu konumda csv dosyanızı bulabileceksiniz:

cd /tmp

scpKomut kullanarak kopyalayın veya nano kullanarak düzenleyin:

nano /tmp/yourOutputFile.csv

4
ve \ o konsolu tekrar yazdırmak için
metdos

2
Bu bir CSV dosyası oluşturmaz, komut çıktısını metin dosyasına (virgülle ayrılmış hale getirmez) kaydeder.
Ruslan Kabalin

@RuslanKabalin evet Sadece bunu fark ettim ve virgülle ayrılmış çıktı (cvs) oluşturmak için talimatı değiştirdim
Marcin Wasiluk

5
Ben "csv" çıktı düzgün kaçmayacak ve bir sql komutu her çalıştırıldığında sonuçları çıktı dosyasına bitiştirildiğini belirterek bu cevabı geliştirirsiniz.
Danny Armstrong

Alan değerlerindeki yeni satırlar ne olacak? COPYYa da \copy(standart CSV biçimine dönüştürmek) doğru kolu yaklaşımları; bunu yapar?
Joker

37

Başlıklar ile birlikte belirli bir tablonun tüm sütunlarıyla ilgileniyorsanız,

COPY table TO '/some_destdir/mycsv.csv' WITH CSV HEADER;

Bu biraz daha basit

COPY (SELECT * FROM table) TO '/some_destdir/mycsv.csv' WITH CSV HEADER;

ki bildiklerime göre eşdeğerdir.


1
Sorgu özelse (IE, sütun takma adlarına sahip veya farklı tablolara katılırsa), başlık, sütun takma adlarını ekranda göründüğü gibi yazdırır.
Devy

34

CSV İhracat Birleştirmesi

Bu bilgi gerçekten iyi temsil edilmiyor. Bunu türetmek için ikinci kez ihtiyacım olduğu için, bunu kendime başka bir şey olmadığını hatırlatmak için buraya koyacağım.

Bunu yapmanın gerçekten en iyi yolu (CSV'yi postgres'ten almak) COPY ... TO STDOUTkomutu kullanmaktır . Yine de buradaki yanıtlarda gösterilen şekilde yapmak istemezsiniz. Komutu kullanmanın doğru yolu:

COPY (select id, name from groups) TO STDOUT WITH CSV HEADER

Sadece bir komutu hatırla!

Ssh üzerinde kullanım için harika:

$ ssh psqlserver.example.com 'psql -d mydb "COPY (select id, name from groups) TO STDOUT WITH CSV HEADER"' > groups.csv

Ssh üzerinde docker içinde kullanmak için harika:

$ ssh pgserver.example.com 'docker exec -tu postgres postgres psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

Yerel makinede bile harika:

$ psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

Yoksa yerel makinedeki liman işçisinin içinde mi?

docker exec -tu postgres postgres psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

Veya bir kubernetes kümesinde, docker'da, HTTPS üzerinde ??:

kubectl exec -t postgres-2592991581-ws2td 'psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

Çok yönlü, çok virgül!

Sen hiç?

Evet yaptım, işte notlarım:

COPYses

Kullanılması /copyetkili bir türlü sistem dosya işlemleri yürütür psqlo çalıştırdığı kullanıcı olarak, komut çalışıyorsa 1 . Uzak bir sunucuya bağlanırsanız, uzak sunucuya psql/ sunucudan yürütülen sistemdeki veri dosyalarını kopyalamak kolaydır .

COPYsunucuda, arka uç işlem kullanıcı hesabı (varsayılan postgres) olarak dosya işlemlerini yürütür , dosya yolları ve izinler denetlenir ve buna göre uygulanır. Kullanılıyorsa, TO STDOUTdosya izinleri denetimleri atlanır.

Bu seçeneklerin her ikisi de psql, sonuçta elde edilen CSV'nin eninde sonunda olmasını istediğiniz yerde sistemde yürütülmüyorsa, sonraki dosya hareketini gerektirir . Deneyimlerime göre, çoğunlukla uzak sunucularla çalıştığınızda bu en olası durum.

Basit CSV çıkışı için ssh üzerinden TCP / IP tüneli gibi bir şeyi uzak bir sisteme yapılandırmak daha karmaşıktır, ancak diğer çıkış biçimleri (ikili) için /copyyerel bir yürütme tünel bağlantısı üzerinden daha iyi olabilir psql. Benzer bir şekilde, büyük ithalatlar için, kaynak dosyayı sunucuya taşımak ve kullanmak COPYmuhtemelen en yüksek performans seçeneğidir.

PSQL Parametreleri

Psql parametreleriyle çıktıyı CSV gibi biçimlendirebilirsiniz, ancak çağrı cihazını devre dışı bırakmayı ve üstbilgileri almayı hatırlamak zorunda kalmak gibi dezavantajlar vardır:

$ psql -P pager=off -d mydb -t -A -F',' -c 'select * from groups;'
2,Technician,Test 2,,,t,,0,,                                                                                                                                                                   
3,Truck,1,2017-10-02,,t,,0,,                                                                                                                                                                   
4,Truck,2,2017-10-02,,t,,0,,

Diğer Aletler

Hayır, bir araç derlemeden ve / veya kurmadan CSV'yi sunucumdan çıkarmak istiyorum.


1
Sonuçlar nereye kaydediliyor? Sorgum çalışıyor ancak dosya bilgisayarımda hiçbir yerde görünmüyor. Ben bunu yapıyorum: KOPYA (a = b seçin, c = d = '1') CSVHEADER İLE STDOUT> abcd.csv
kRazzy R

1
@kRazzyR Çıktı psql komutunun stdout'una gider, bu yüzden nihayetinde stdout ile yaptığınız her şey verinin nereye gittiğidir. Örneklerimde bir dosyaya yönlendirmek için '> file.csv' kullanıyorum. Psql -c parametresi aracılığıyla sunucuya gönderilen komutun dışında olduğundan emin olmak istiyorsunuz. 'Yerel makine' örneğine bakın.
joshperry

Tam açıklama için teşekkürler. Copy komutu psql ile umutsuzca karmaşıktır. Genellikle veri dosyalarını içe ve dışa aktarmak için ücretsiz bir veritabanı istemcisi (dbeaver topluluk sürümü) kullanıyorum. Güzel haritalama ve biçimlendirme araçları sağlar. Cevabınız uzak sistemlerden kopyalama için mükemmel ayrıntılı örnekler sağlar.
Rich Lysakowski Doktora

24

Hata iletisini aldığım için \ COPY kullanmalıydım:

ERROR:  could not open file "/filepath/places.csv" for writing: Permission denied

Ben de kullandım:

\Copy (Select address, zip  From manjadata) To '/filepath/places.csv' With CSV;

ve çalışıyor


17

psql bunu sizin için yapabilir:

edd@ron:~$ psql -d beancounter -t -A -F"," \
                -c "select date, symbol, day_close " \
                   "from stockprices where symbol like 'I%' " \
                   "and date >= '2009-10-02'"
2009-10-02,IBM,119.02
2009-10-02,IEF,92.77
2009-10-02,IEV,37.05
2009-10-02,IJH,66.18
2009-10-02,IJR,50.33
2009-10-02,ILF,42.24
2009-10-02,INTC,18.97
2009-10-02,IP,21.39
edd@ron:~$

man psqlBurada kullanılan seçeneklerle ilgili yardım için bkz .


12
Bu gerçek bir CSV dosyası değil - verilerde virgül varsa yanmasını izleyin - bu nedenle dahili COPY desteğini kullanmak tercih edilir. Ancak bu genel teknik, CSG'nin yanı sıra diğer sınırlandırılmış biçimlerde Postgres'ten dışa aktarma için hızlı bir saldırı olarak kullanışlıdır.
Greg Smith

17

Yeni sürüm - psql 12 - destekleyecektir --csv.

psql - devel

--csv

CSV (Virgülle Ayrılmış Değerler) çıkış moduna geçer. Bu \ pset format csv'ye eşdeğerdir .


csv_fieldsep

CSV çıktı biçiminde kullanılacak alan ayırıcısını belirtir. Ayırıcı karakter bir alanın değerinde görünürse, bu alan standart CSV kurallarına göre çift tırnak içinde verilir. Varsayılan, virgüldür.

Kullanımı:

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv  postgres

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv -P csv_fieldsep='^'  postgres

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv  postgres > output.csv

16

Bu COPY TOözelliği desteklemeyen AWS Redshift üzerinde çalışıyorum .

BI aracım sekmeyle ayrılmış CSV'leri destekliyor, bu yüzden aşağıdakileri kullandım:

 psql -h dblocation -p port -U user -d dbname -F $'\t' --no-align -c "SELECT * FROM TABLE" > outfile.csv

11

PgAdmin III'te, sorgu penceresinden dosyaya dışa aktarma seçeneği vardır. Ana menüde Sorgu -> Dosyaya yürüt veya aynı şeyi yapan bir düğme var (sadece sorguyu çalıştıran düz yeşil üçgenin aksine mavi disketli yeşil bir üçgen). Sorguyu sorgu penceresinden çalıştırmıyorsanız, IMSoP'nin önerdiğini yaparım ve copy komutunu kullanırdım.


Süper bir yönetici olmam gerektiğinden IMSoP'un yanıtı benim için işe yaramadı. Bu bir tedavi çalıştı. Teşekkürler!
Mike

9

Birkaç şeyi denedim, ancak birkaçı bana başlık detaylarıyla istenen CSV'yi verebildi.

İşte benim için işe yarayan.

psql -d dbame -U username \
  -c "COPY ( SELECT * FROM TABLE ) TO STDOUT WITH CSV HEADER " > \
  OUTPUT_CSV_FILE.csv

9

Deseni psql2csvkapsüle eden COPY query TO STDOUTve uygun CSV ile sonuçlanan küçük bir araç yazdım . Arayüzü benzer psql.

psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY

Sorgunun, varsa STDIN içeriği veya son bağımsız değişken olduğu varsayılır. Aşağıdakiler haricinde diğer tüm argümanlar psql'ye iletilir:

-h, --help           show help, then exit
--encoding=ENCODING  use a different encoding than UTF8 (Excel likes LATIN1)
--no-header          do not output a header

2
Harika çalışıyor. Teşekkür ederim.
AlexM

6

Daha uzun sorgunuz varsa ve psql kullanmak istiyorsanız, sorgunuzu bir dosyaya yerleştirin ve aşağıdaki komutu kullanın:

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv

FWIW, MS Excel'de doğru bir şekilde açılacak bir CSV dosyası oluşturmak -F","yerine kullanmak zorunda kaldım-F";"
CFL_Jeff

4

Sütun adlarına sahip CSV dosyasını HEADER olarak indirmek için şu komutu kullanın:

Copy (Select * From tableName) To '/tmp/fileName.csv' With CSV HEADER;

1

DataGrip , JetBrains tarafından bir veritabanı IDE tavsiye . Sen edebilir bir CSV dosyasına bir SQL sorgusu ihracat ve kolaylıkla SSH tünel ayarlayabilirsiniz. Belgeler "sonuç kümesi" ne atıfta bulunursa, konsoldaki bir SQL sorgusu tarafından döndürülen sonucu ifade eder.

DataGrip ile ilişkili değilim, sadece ürünü seviyorum!


Ben downvote bağlam / açıklama eksikliği nedeniyle olduğunu tahmin, bu yüzden DataGrip belgelerine bağladım. Aşağı oy için farklı bir neden varsa, lütfen bana bildirin. Yukarıdaki CLI çözümlerini kullandım ve DataGrip daha küçük sorgular için çok daha kolay.
skeller88

DataGrip ile ilgili sorun, cüzdanınızı kavramasıdır. Ücretsiz değil. DBeaver'ın topluluk sürümünü şu adreste deneyin: deneyin . Tüm popüler veritabanlarını destekleyen SQL programcıları, DBA'lar ve analistler için bir FOSS çok platformlu veritabanı aracıdır: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, vb.
Rich Lysakowski Doktora

Cool bunu kontrol edeceğim. Yorumunuzu bir cevap olarak da yeniden yayınlamaya ne dersiniz?
skeller88

0

Web tarayıcınızda bir veritabanı istemcisi olan JackDB bunu gerçekten kolaylaştırıyor. Özellikle Heroku'daysan.

Uzak veritabanlarına bağlanmanıza ve üzerlerinde SQL sorguları çalıştırmanıza olanak tanır.

                                                                                                                                                       Kaynak (kaynak: jackdb.com )jackdb-Heroku


DB'niz bağlandıktan sonra bir sorgu çalıştırabilir ve CSV veya TXT'ye dışa aktarabilirsiniz (sağ alt kısma bakın).


jackdb ihracatı

Not: Hiçbir şekilde JackDB'ye bağlı değilim. Şu anda ücretsiz hizmetlerini kullanıyorum ve harika bir ürün olduğunu düşünüyorum.


0

@ Skeller88'in isteği üzerine, her yanıtı okumayan insanlar tarafından kaybolmaması için yorumumu bir cevap olarak yeniden gönderiyorum ...

DataGrip ile ilgili sorun, cüzdanınızı kavramasıdır. Ücretsiz değil. DBeaver'ın topluluk sürümünü dbeaver.io adresinde deneyin. Tüm popüler veritabanlarını destekleyen SQL programcıları, DBA'lar ve analistler için bir FOSS çok platformlu veritabanı aracıdır: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, vb.

DBeaver Community Edition, bir veritabanına bağlanmayı, verileri almak için sorgular yayınlamayı ve ardından CSV, JSON, SQL veya diğer yaygın veri biçimlerine kaydetmek için sonuç kümesini indirmeyi önemsiz kılar. Postgres için TOAD, SQL Server için TOAD veya Oracle için Toad için uygun bir FOSS rakibi.

DBeaver ile hiçbir bağlantım yok. Fiyat ve işlevselliği seviyorum, ancak keşke kullanıcıların DBeaver / Eclipse uygulamasını daha fazla açmasını ve kullanıcıların doğrudan grafik ve grafikler oluşturmak için yıllık abonelik için ödeme yapmasını istemek yerine DBeaver / Eclipse'a analitik widget'ları eklemesini kolaylaştırdı. uygulama. Java kodlama becerilerim paslı ve Eclipse widget'larının nasıl oluşturulacağını öğrenmek için haftalar sürmekten hoşlanmıyorum, sadece DBeaver'ın DBeaver Topluluk Sürümü'ne üçüncü taraf widget'ları ekleme yeteneğini devre dışı bıraktığını bulmak için.

DBeaver kullanıcıları, DBeaver'ın Topluluk Sürümü'ne eklemek üzere analitik widget'ları oluşturma adımları hakkında bilgi sahibi mi?


-3
import json
cursor = conn.cursor()
qry = """ SELECT details FROM test_csvfile """ 
cursor.execute(qry)
rows = cursor.fetchall()

value = json.dumps(rows)

with open("/home/asha/Desktop/Income_output.json","w+") as f:
    f.write(value)
print 'Saved to File Successfully'

3
Lütfen cevabı düzenlediğinizi açıklayın, yalnızca koddan kaçının
GGO

3
Kısa süreli sınırlı yardım sağlayabilecek bu kod snippet'i için teşekkür ederiz. Düzgün bir açıklama , bunun neden problem için iyi bir çözüm olduğunu göstererek uzun vadeli değerini büyük ölçüde artıracak ve diğer benzer sorularla gelecekteki okuyucular için daha yararlı hale getirecektir. Yaptığınız varsayımlar dahil bazı açıklamalar eklemek için lütfen yanıtınızı düzenleyin .
Toby Speight

2
Bu bir csv dosyası değil, bir json dosyası üretecektir.
nvoigt
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.