Simpan keluaran PL / pgSQL dari PostgreSQL ke file CSV

Jawaban:

1368

Apakah Anda ingin file yang dihasilkan di server, atau di klien?

Sisi server

Jika Anda menginginkan sesuatu yang mudah digunakan kembali atau diotomatisasi, Anda dapat menggunakan perintah COPY bawaan Postgresql . misalnya

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

Pendekatan ini berjalan sepenuhnya pada server jauh - tidak dapat menulis ke PC lokal Anda. Itu juga perlu dijalankan sebagai "pengguna super" Postgres (biasanya disebut "root") karena Postgres tidak dapat menghentikannya melakukan hal-hal buruk dengan sistem file lokal mesin itu.

Itu tidak benar-benar berarti Anda harus terhubung sebagai superuser (mengotomatisasi yang akan menjadi risiko keamanan dari jenis yang berbeda), karena Anda dapat menggunakan yang SECURITY DEFINERpilihan untukCREATE FUNCTION membuat fungsi yang berjalan seolah-olah Anda superuser .

Bagian penting adalah bahwa fungsi Anda ada untuk melakukan pemeriksaan tambahan, tidak hanya memotong keamanan - sehingga Anda dapat menulis fungsi yang mengekspor data persis yang Anda butuhkan, atau Anda dapat menulis sesuatu yang dapat menerima berbagai pilihan selama mereka temui daftar putih yang ketat. Anda perlu memeriksa dua hal:

  1. File mana yang harus pengguna baca / tulis pada disk? Ini mungkin direktori tertentu, misalnya, dan nama file mungkin harus memiliki awalan atau ekstensi yang sesuai.
  2. Tabel mana yang harus dibaca / ditulis oleh pengguna dalam basis data? Ini biasanya didefinisikan oleh GRANTs dalam database, tetapi fungsinya sekarang berjalan sebagai superuser, sehingga tabel yang biasanya "di luar batas" akan dapat diakses sepenuhnya. Anda mungkin tidak ingin membiarkan seseorang memanggil fungsi Anda dan menambahkan baris di akhir tabel "pengguna" Anda ...

Saya telah menulis posting blog yang diperluas dengan pendekatan ini , termasuk beberapa contoh fungsi yang mengekspor (atau mengimpor) file dan tabel yang memenuhi persyaratan ketat.


Sisi klien

Pendekatan lain adalah melakukan penanganan file di sisi klien , yaitu di aplikasi atau skrip Anda. Server Postgres tidak perlu tahu file apa yang Anda salin, hanya memuntahkan data dan klien meletakkannya di suatu tempat.

Sintaks dasar untuk ini adalah COPY TO STDOUTperintah, dan alat grafis seperti pgAdmin akan membungkusnya untuk Anda dalam dialog yang bagus.

The psqlbaris perintah klien memiliki khusus "meta-command" yang disebut \copy, yang mengambil semua pilihan sama dengan "nyata" COPY, tetapi dijalankan dalam klien:

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

Perhatikan bahwa tidak ada terminasi ;, karena meta-command diakhiri oleh baris baru, tidak seperti perintah SQL.

Dari dokumen :

Jangan bingung COPY dengan instruksi psql \ copy. \ copy meminta COPY DARI STDIN atau COPY TO STDOUT, dan kemudian mengambil / menyimpan data dalam file yang dapat diakses oleh klien psql. Dengan demikian, aksesibilitas file dan hak akses bergantung pada klien daripada server ketika \ copy digunakan.

Bahasa pemrograman aplikasi Anda juga mungkin memiliki dukungan untuk mendorong atau mengambil data, tetapi Anda umumnya tidak dapat menggunakan COPY FROM STDIN/ TO STDOUTdalam pernyataan SQL standar, karena tidak ada cara untuk menghubungkan aliran input / output. PostgreSQL handler PHP ( bukan PDO) mencakup fungsi yang sangat mendasar pg_copy_fromdan pg_copy_toyang disalin ke / dari array PHP, yang mungkin tidak efisien untuk set data besar.

IMSoP
sumber
131
Jelas contoh di atas kadang-kadang mengharuskan pengguna untuk menjadi superuser, ini adalah versi untuk orang biasa;) gema "COPY (SELECT * from foo) UNTUK STDOUT dengan CSV HEADER" | psql -o '/tmp/test.csv' database_name
Drachenfels
10
@Drachenfels: \copyberfungsi juga - di sana, jalur relatif ke klien, dan tidak ada titik koma yang diperlukan / diizinkan. Lihat hasil edit saya.
krlmlr
3
@IMSoP: Bagaimana Anda menambahkan pernyataan COPY ke fungsi sql (on postgres 9.3)? Jadi kueri akan disimpan ke file .csv?
jO.
12
Sepertinya \copyperlu menjadi satu-liner. Jadi Anda tidak mendapatkan keindahan memformat sql seperti yang Anda inginkan, dan hanya menempatkan salinan / fungsi di sekitarnya.
isaaclw
1
@AndreSilva Sebagai jawaban menyatakan, \copyadalah meta-perintah khusus di psqlklien baris perintah . Itu tidak akan berfungsi pada klien lain, seperti pgAdmin; mereka mungkin akan memiliki alat sendiri, seperti penyihir grafis, untuk melakukan pekerjaan ini.
IMSoP
519

Ada beberapa solusi:

1 psqlperintah

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

Ini memiliki keuntungan besar yang bisa Anda gunakan melalui SSH, seperti ssh postgres@host command- memungkinkan Anda untuk mendapatkannya

2 copyperintah postgres

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

3 psql interaktif (atau tidak)

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

Semuanya bisa digunakan dalam skrip, tapi saya lebih suka # 1.

4 pgadmin tapi itu tidak bisa skrip.

Sorin
sumber
32
IMHO opsi pertama adalah rawan kesalahan, karena itu tidak termasuk pelolosan koma dalam data yang diekspor.
Piohen
4
Juga, psql tidak mengutip nilai sel, jadi jika APAPUN data Anda menggunakan pembatas, file Anda akan rusak.
Cerin
7
@Cerin -t adalah sinonim untuk --tuples-only (matikan pencetakan nama kolom dan footer jumlah hitung hasil, dll.) - hilangkan untuk mendapatkan tajuk kolom
ic3b3rg
21
Baru saja menguji klaim yang lolos koma — benar, metode # 1 tidak luput dari koma dalam nilai.
MrColes
1
juga menggunakan "\ pset footer" sehingga jumlah baris tidak mencangkup dalam file
techbrownbags
94

Di terminal (saat terhubung ke db) atur output ke file cvs

1) Setel pemisah bidang ke ',':

\f ','

2) Setel format output tidak selaras:

\a

3) Hanya tampilkan tupel:

\t

4) Tetapkan output:

\o '/tmp/yourOutputFile.csv'

5) Jalankan permintaan Anda:

:select * from YOUR_TABLE

6) Output:

\o

Anda kemudian dapat menemukan file csv Anda di lokasi ini:

cd /tmp

Salin menggunakan scpperintah atau edit menggunakan nano:

nano /tmp/yourOutputFile.csv
Marcin Wasiluk
sumber
4
dan \ o untuk mencetak konsol lagi
metdos
2
Ini tidak akan menghasilkan file CSV, itu hanya akan merekam output perintah ke file teks (yang tidak membuatnya dipisahkan dengan koma).
Ruslan Kabalin
@RuslanKabalin ya saya baru saja memperhatikan itu dan mengubah instruksi untuk membuat output yang dipisahkan koma (cvs)
Marcin Wasiluk
5
Saya akan memperbaiki jawaban ini dengan mencatat bahwa output "csv" tidak akan dapat di-escape dengan benar dan setiap kali perintah sql dieksekusi hasilnya disatukan dengan file output.
Danny Armstrong
Bagaimana dengan baris baru dalam nilai bidang? The COPYatau \copypendekatan menangani dengan benar (convert ke format CSV standar); Melakukan hal ini?
Wildcard
37

Jika Anda tertarik pada semua kolom tabel tertentu bersama dengan header, Anda bisa menggunakannya

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

Ini sedikit lebih sederhana daripada

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

yang, setahu saya, setara.

benjwadams
sumber
1
Jika kueri kustom (IE alias alias kolom atau bergabung dengan tabel yang berbeda), header akan mencetak alias kolom seperti yang ditampilkan di layar.
Devy
34

Unifikasi Ekspor CSV

Informasi ini tidak terwakili dengan baik. Karena ini adalah kedua kalinya saya perlu menurunkan ini, saya akan meletakkan ini di sini untuk mengingatkan diri saya jika tidak ada yang lain.

Sungguh cara terbaik untuk melakukan ini (mengeluarkan CSV dari postgres) adalah dengan menggunakan COPY ... TO STDOUTperintah. Meskipun Anda tidak ingin melakukannya dengan cara yang ditunjukkan dalam jawaban di sini. Cara yang benar untuk menggunakan perintah adalah:

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

Ingat hanya satu perintah!

Ini bagus untuk digunakan lebih dari ssh:

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

Ini bagus untuk digunakan di dalam docker di atas ssh:

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

Ini bahkan hebat di mesin lokal:

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

Atau di dalam buruh pelabuhan di mesin lokal ?:

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

Atau di cluster kubernetes, di buruh pelabuhan, melalui HTTPS ??:

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

Sangat fleksibel, banyak koma!

Apakah kamu bahkan

Ya saya lakukan, ini catatan saya:

COPYses

Menggunakan /copyoperasi file yang dijalankan secara efektif pada sistem apa pun yang psqldijalankan perintah, sebagai pengguna yang menjalankannya 1 . Jika Anda terhubung ke server jarak jauh, mudah untuk menyalin file data pada sistem yang menjalankan psqlke / dari server jarak jauh.

COPYmengeksekusi operasi file di server sebagai akun pengguna proses backend (default postgres), jalur file dan izin diperiksa dan diterapkan sesuai. Jika menggunakan TO STDOUTmaka pemeriksaan file izin dilewati.

Kedua opsi ini memerlukan perpindahan file selanjutnya jika psqltidak dijalankan pada sistem di mana Anda ingin CSV yang dihasilkan berada. Ini adalah kasus yang paling mungkin, menurut pengalaman saya, ketika Anda kebanyakan bekerja dengan server jarak jauh.

Lebih kompleks untuk mengkonfigurasi sesuatu seperti terowongan TCP / IP lewat ssh ke sistem jarak jauh untuk output CSV sederhana, tetapi untuk format output lainnya (biner) mungkin lebih baik untuk /copymelewati koneksi tunneled, mengeksekusi lokal psql. Dalam nada yang sama, untuk impor besar, memindahkan file sumber ke server dan menggunakan COPYmungkin merupakan opsi dengan kinerja tertinggi.

Parameter PSQL

Dengan parameter psql Anda dapat memformat output seperti CSV tetapi ada kelemahannya karena harus ingat untuk menonaktifkan pager dan tidak mendapatkan header:

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

Alat Lainnya

Tidak, saya hanya ingin mengeluarkan CSV dari server saya tanpa mengkompilasi dan / atau menginstal alat.

Joshperry
sumber
1
Di mana hasil disimpan? Kueri saya berjalan tetapi file tidak muncul di mana pun di komputer saya. Inilah yang saya lakukan: COPY (pilih a, b dari c di mana d = '1') UNTUK STDOUT DENGAN CSVHEADER> abcd.csv
kRazzy R
1
@ kRazzyR Outputnya pergi ke stdout dari perintah psql, jadi pada akhirnya apa pun yang Anda lakukan dengan stdout adalah tempat data berjalan. Dalam contoh saya, saya menggunakan '> file.csv' untuk mengarahkan ulang ke file. Anda ingin memastikan bahwa itu di luar perintah yang dikirim ke server melalui parameter psql -c. Lihat contoh 'mesin lokal'.
Joshperry
1
Terima kasih atas penjelasan lengkapnya. Perintah salin sangat kompleks dengan psql. Saya biasanya menggunakan klien basis data gratis (edisi komunitas dbeaver) untuk mengimpor dan mengekspor file data. Ini menyediakan alat pemetaan dan format yang bagus. Jawaban Anda memberikan contoh terperinci untuk menyalin dari sistem jarak jauh.
Rich Lysakowski PhD
24

Saya harus menggunakan \ COPY karena saya menerima pesan kesalahan:

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

Jadi saya menggunakan:

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

dan berfungsi

maudulus
sumber
17

psql dapat melakukan ini untuk Anda:

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:~$

Lihat man psqlbantuan tentang opsi yang digunakan di sini.

Dirk Eddelbuettel
sumber
12
Ini bukan file CSV yang sebenarnya - tonton dibakar jika ada koma dalam data - jadi lebih disukai menggunakan dukungan COPY bawaan. Tetapi teknik umum ini berguna sebagai peretasan cepat untuk mengekspor dari Postgres dalam format terbatas lainnya selain CSV.
Greg Smith
17

Versi baru - psql 12 - akan mendukung --csv.

psql - devel

--csv

Beralih ke mode keluaran CSV (Comma-Separated Values). Ini sama dengan \ pset format csv .


csv_fieldsep

Menentukan pemisah bidang yang akan digunakan dalam format output CSV. Jika karakter pemisah muncul dalam nilai bidang, bidang itu adalah output dalam tanda kutip ganda, mengikuti aturan standar CSV. Standarnya adalah koma.

Pemakaian:

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
Lukasz Szozda
sumber
16

Saya sedang mengerjakan AWS Redshift, yang tidak mendukung COPY TOfitur ini.

Alat BI saya mendukung CSV pembatasan-tab, jadi saya menggunakan yang berikut:

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

Di pgAdmin III ada opsi untuk mengekspor ke file dari jendela kueri. Di menu utama itu Permintaan -> Jalankan ke file atau ada tombol yang melakukan hal yang sama (itu adalah segitiga hijau dengan floppy disk biru sebagai lawan dari segitiga hijau polos yang hanya menjalankan permintaan). Jika Anda tidak menjalankan kueri dari jendela kueri, maka saya akan melakukan apa yang disarankan IMSoP dan menggunakan perintah salin.

Amanda Nyren
sumber
Jawaban IMSoP tidak bekerja untuk saya karena saya harus menjadi admin super. Ini berhasil. Terima kasih!
Mike
9

Saya mencoba beberapa hal tetapi beberapa di antaranya mampu memberi saya CSV yang diinginkan dengan detail tajuk.

Inilah yang bekerja untuk saya.

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

Saya telah menulis alat kecil yang disebut psql2csvmerangkum COPY query TO STDOUTpola, menghasilkan CSV yang tepat. Antarmukanya mirip dengan psql.

psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY

Permintaan diasumsikan sebagai isi STDIN, jika ada, atau argumen terakhir. Semua argumen lain diteruskan ke psql kecuali untuk ini:

-h, --help           show help, then exit
--encoding=ENCODING  use a different encoding than UTF8 (Excel likes LATIN1)
--no-header          do not output a header
fphilipe
sumber
2
Bagus sekali. Terima kasih.
AlexM
6

Jika Anda memiliki kueri yang lebih panjang dan Anda ingin menggunakan psql kemudian masukkan kueri Anda ke file dan gunakan perintah berikut:

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv
Andres Kull
sumber
FWIW, saya harus menggunakan -F","daripada -F";"menghasilkan file CSV yang akan terbuka dengan benar di MS Excel
CFL_Jeff
4

Untuk Mengunduh file CSV dengan nama kolom sebagai HEADER gunakan perintah ini:

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

Saya sangat merekomendasikan DataGrip , IDE basis data oleh JetBrains. Anda dapat mengekspor kueri SQL ke file CSV , dan dapat mengatur tunneling ssh dengan mudah. Ketika dokumentasi merujuk ke "set hasil", itu berarti hasil dikembalikan oleh kueri SQL di konsol.

Saya tidak terkait dengan DataGrip, saya suka produk ini!

skeller88
sumber
Saya menduga downvote disebabkan oleh kurangnya konteks / penjelasan, jadi saya telah menautkan ke dokumentasi DataGrip. Jika ada alasan berbeda untuk downvote, harap beri tahu saya. Saya telah menggunakan solusi CLI di atas dan DataGrip jauh lebih mudah untuk pertanyaan yang lebih kecil.
skeller88
Masalah dengan DataGrip adalah bahwa ia mencengkeram dompet Anda. Ini tidak gratis. Coba edisi komunitas DBeaver di dbeaver.io . Ini adalah alat basis data multi-platform FOSS untuk pemrogram SQL, DBA dan analis yang mendukung semua basis data populer: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, dll.
Rich Lysakowski PhD
Keren, aku akan memeriksanya. Bagaimana dengan Anda memposting ulang komentar Anda sebagai jawaban juga?
skeller88
0

JackDB , klien basis data di peramban web Anda, menjadikan ini sangat mudah. Apalagi jika Anda menggunakan Heroku.

Ini memungkinkan Anda terhubung ke basis data jauh dan menjalankan query SQL pada mereka.

                                                                                                                                                       Sumber (sumber: jackdb.com )jackdb-heroku


Setelah DB terhubung, Anda dapat menjalankan kueri dan mengekspor ke CSV atau TXT (lihat kanan bawah).


jackdb-ekspor

Catatan: Saya sama sekali tidak berafiliasi dengan JackDB. Saat ini saya menggunakan layanan gratis mereka dan berpikir itu adalah produk hebat.

Dennis
sumber
0

Sesuai permintaan @ skeller88, saya mengepos ulang komentar saya sebagai jawaban agar tidak hilang oleh orang-orang yang tidak membaca setiap tanggapan ...

Masalah dengan DataGrip adalah bahwa ia mencengkeram dompet Anda. Ini tidak gratis. Coba edisi komunitas DBeaver di dbeaver.io. Ini adalah alat database multi-platform FOSS untuk pemrogram SQL, DBA, dan analis yang mendukung semua basis data populer: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, dll.

DBeaver Community Edition membuatnya sepele untuk terhubung ke database, mengeluarkan pertanyaan untuk mengambil data, dan kemudian mengunduh hasil yang ditetapkan untuk menyimpannya ke CSV, JSON, SQL, atau format data umum lainnya. Ini adalah pesaing FOSS yang layak untuk TOAD untuk Postgres, TOAD untuk SQL Server, atau Toad untuk Oracle.

Saya tidak memiliki afiliasi dengan DBeaver. Saya suka harga dan fungsionalitasnya, tetapi saya berharap mereka akan membuka aplikasi DBeaver / Eclipse lebih banyak dan membuatnya mudah untuk menambahkan widget analytics ke DBeaver / Eclipse, daripada meminta pengguna untuk membayar langganan tahunan untuk membuat grafik dan grafik langsung di dalam aplikasi. Keahlian coding Java saya berkarat dan saya merasa tidak butuh waktu berminggu-minggu untuk mempelajari kembali cara membuat widget Eclipse, hanya untuk menemukan bahwa DBeaver telah menonaktifkan kemampuan untuk menambahkan widget pihak ketiga ke Edisi Komunitas DBeaver.

Apakah pengguna DBeaver memiliki wawasan tentang langkah-langkah untuk membuat widget analytics untuk ditambahkan ke Edisi Komunitas DBeaver?

Rich Lysakowski PhD
sumber
-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'
pengguna9279273
sumber
3
Tolong laporkan apa yang Anda lakukan dengan mengedit jawaban, hindari hanya jawaban kode
GGO
3
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan jangka pendek terbatas. Penjelasan yang tepat akan sangat meningkatkan nilai jangka panjangnya dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini, dan akan membuatnya lebih bermanfaat bagi pembaca masa depan dengan pertanyaan lain yang serupa. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan, termasuk asumsi yang Anda buat.
Toby Speight
2
Ini akan menghasilkan file json, bukan file csv.
novigt