PostgreSQLからのPL / pgSQL出力をCSVファイルに保存する


回答:


1368

結果のファイルをサーバーまたはクライアントのどちらに置きますか?

サーバ側

再利用や自動化が簡単なものが必要な場合は、Postgresqlの組み込みのCOPYコマンドを使用できます。例えば

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

このアプローチは完全にリモートサーバーで実行されます -ローカルPCに書き込むことはできません。また、Postgresはそのマシンのローカルファイルシステムで厄介なことを行うのを止めることができないため、Postgresの「スーパーユーザー」(通常は「ルート」と呼ばれます)として実行する必要があります。

これは、実際にはスーパーユーザーとして接続する必要があるという意味ではありません(自動化すると、別の種類のセキュリティリスクになります)。このSECURITY DEFINERオプションをCREATE FUNCTION使用し、スーパーユーザーであるかのように実行される関数を作成できます

重要な部分は、セキュリティを回避するだけでなく、追加のチェックを実行するための関数があることです。つまり、必要な正確なデータをエクスポートする関数を記述したり、さまざまなオプションを受け入れることができるものを記述したりできます。厳格なホワイトリストを満たします。次の2つを確認する必要があります。

  1. ユーザーがディスク上で読み書きできるのはどのファイルですか?たとえば、これは特定のディレクトリである場合があり、ファイル名には適切な接頭辞または拡張子を付ける必要があります。
  2. ユーザーがデータベースで読み書きできるテーブルはどれですか。これは通常GRANT、データベース内のs によって定義されますが、関数は現在スーパーユーザーとして実行されているため、通常「範囲外」にあるテーブルに完全にアクセスできます。おそらく、誰かに関数を呼び出させて、「users」テーブルの最後に行を追加させたくないでしょう…

私はこのアプローチを拡張するブログ投稿を書きまし。厳密な条件を満たすファイルとテーブルをエクスポート(またはインポート)する関数のいくつかの例を含みます。


クライアント側

もう1つの方法は、クライアント側、つまりアプリケーションまたはスクリプトでファイル処理行うことです。Postgresサーバーは、コピー先のファイルを知る必要はありません。データを吐き出すだけで、クライアントはそれをどこかに置きます。

これの基礎となる構文はCOPY TO STDOUTコマンドであり、pgAdminのようなグラフィカルツールはそれを素敵なダイアログでラップします。

psqlコマンドラインクライアントは、と呼ばれる特殊な「メタコマンド」持っている\copy「本物」のように、すべて同じオプションを取り、COPYが、クライアント内で実行されます。

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

;SQLコマンドとは異なり、メタコマンドは改行で終了するため、終了はありません。

ドキュメントから:

COPYをpsql命令\ copyと混同しないでください。\ copyはCOPY FROM STDINまたはCOPY TO STDOUTを呼び出してから、psqlクライアントがアクセスできるファイルにデータをフェッチ/保存します。したがって、\ copyを使用すると、ファイルのアクセス可能性とアクセス権はサーバーではなくクライアントに依存します。

アプリケーションプログラミング言語データのプッシュまたはフェッチをサポートしている場合がありますが、入力/出力ストリームを接続する方法がないため、標準のSQLステートメント内でCOPY FROM STDIN/を使用することはできませんTO STDOUT。PHPのPostgreSQLハンドラー(PDOではない)には、PHP配列pg_copy_fromとの間pg_copy_toでコピーを行う非常に基本的な関数が含まれています。


131
明らかに上記の例では、ユーザーがスーパーユーザーである必要がある場合があります。これは一般ユーザー向けのバージョンです;)echo "COPY(SELECT * from foo)TO STDOUT with CSV HEADER" | psql -o '/tmp/test.csv' database_name
Drachenfels

10
@Drachenfels:\copy動作します-パスはクライアントからの相対パスであり、セミコロンは必要ありません/許可されていません。私の編集を参照してください。
krlmlr 2013

3
@IMSoP:SQL(postgres 9.3)関数にどのようにCOPYステートメントを追加しますか?したがって、クエリは.csvファイルに保存されますか?
jO。

12
\copyワンライナーである必要があるようです。そのため、SQLを希望どおりにフォーマットし、コピー/関数を配置するだけの美しさは得られません。
isaaclw 2014年

1
@AndreSilva回答のとおり、コマンドラインクライアントの\copy特別なメタコマンドです。pgAdminなどの他のクライアントでは機能しません。彼らはおそらく、この作業を行うためのグラフィカルウィザードなどの独自のツールを持っています。psql
IMSoP 2018年

519

いくつかの解決策があります:

1 psqlコマンド

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

以下のようにこれは、あなたがSSH経由でそれを使用できるという大きな利点がありssh postgres@host command得るためにあなたを可能に-

2 postgres copyコマンド

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

3 psqlインタラクティブ(またはそうでない)

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

それらはすべてスクリプトで使用できますが、私は#1を好みます。

4 pgadminですが、スクリプト化できません。


32
IMHO最初のオプションは、エクスポートされたデータにコンマの適切なエスケープが含まれていないため、エラーが発生しやすくなります。
ピオヘン2013年

4
また、psqlはそうならば、セルの値を引用しないANYあなたのデータのデリミタを使用して、あなたのファイルが破損します。
セリン14

7
@Cerin -tは--tuples-onlyの同義語です(列名や結果の行数フッターの印刷をオフにするなど)-省略して列ヘッダーを取得します
ic3b3rg

21
カンマエスケープクレームをテストしたところ、それは事実です。方法#1は、値のカンマをエスケープしませ
MrColes 14

1
また、「\ pset footer」を使用して、ファイルの行数が
増え

94

端末で(dbに接続している間)出力をcvsファイルに設定します

1)フィールドセパレータを','次のように設定します。

\f ','

2)出力形式を揃えずに設定します。

\a

3)タプルのみを表示:

\t

4)出力を設定します。

\o '/tmp/yourOutputFile.csv'

5)クエリを実行します。

:select * from YOUR_TABLE

6)出力:

\o

その後、この場所でcsvファイルを見つけることができます。

cd /tmp

scpコマンドを使用してコピーするか、nanoを使用して編集します。

nano /tmp/yourOutputFile.csv

4
コンソールをもう一度印刷するために、\ o
メトス

2
これはCSVファイルを作成せず、コマンド出力をテキストファイルに記録するだけです(コンマで区切られません)。
Ruslan Kabalin

@RuslanKabalinはい私はそれに気づき、コンマ区切りの出力(cvs)を作成するための指示を修正しました
Marcin Wasiluk

5
「csv」出力が適切にエスケープされず、sqlコマンドが実行されるたびに結果が出力ファイルに連結されることに注意して、この答えを改善します。
ダニーアームストロング

フィールド値の改行はどうですか?COPYまたは\copy正しくハンドル(標準CSV形式に変換)に近づきます。これは?
ワイルドカード2017年

37

ヘッダーとともに特定のテーブルのすべての列に興味がある場合は、

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

これは、

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

私の知る限り、これは同等です。


1
クエリがカスタム(列のエイリアスを持つ、または異なるテーブルを結合する)の場合、ヘッダーは画面に表示されるとおりに列のエイリアスを出力します。
Devy 2013年

34

CSVエクスポートの統合

この情報は実際にはよく表されていません。これを導出する必要があったのは今回が2回目なので、これをここに置いて、他に何もないことを思い出させます。

本当にこれを行う(postgresからCSVを取得する)ための最良の方法は、COPY ... TO STDOUTコマンドを使用することです。あなたはそれをここの答えに示されている方法でしたくないのですが。コマンドを使用する正しい方法は次のとおりです。

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

コマンドは1つだけ覚えてください。

sshでの使用に最適です。

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

ssh経由でdocker内で使用するのに最適です。

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

ローカルマシンでさえ素晴らしいです:

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

またはローカルマシンのDockerの内部?:

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

または、Kubernetesクラスター、Docker、HTTPS経由??:

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

とても用途が広く、カンマがたくさん!

あなたも?

はい、私はしました、ここに私のメモがあります:

コピー

を使用/copyすると、psqlコマンドを実行しているユーザーとして、コマンドが実行されているシステムでファイル操作を効率的に実行できます1。リモートサーバーに接続する場合、リモートサーバーとの間で実行中のシステム上のデータファイルをコピーするのは簡単psqlです。

COPYバックエンドプロセスのユーザーアカウント(デフォルトpostgres)としてサーバー上でファイル操作を実行し、ファイルパスと権限がチェックされ、それに応じて適用されます。使用する場合TO STDOUT、ファイルのアクセス権チェックはバイパスされます。

psql結果のCSVを最終的に常駐させたいシステムでが実行されていない場合、これらのオプションの両方で後続のファイル移動が必要です。これは、私の経験では、ほとんどの場合、ほとんどがリモートサーバーで作業する場合です。

単純なCSV出力の場合、sshを介してリモートシステムへのTCP / IPトンネルのようなものを構成するのはより複雑ですが、他の出力形式(バイナリ)の場合は/copy、トンネル接続を介してローカルを実行する方がよい場合がありますpsql。同様に、大規模なインポートでは、ソースファイルをサーバーに移動して使用することCOPYがおそらく最もパフォーマンスの高いオプションです。

PSQLパラメーター

psqlパラメーターを使用すると、CSVのように出力をフォーマットできますが、ポケットベルを無効にすることを忘れずにヘッダーを取得しないなどの欠点があります。

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

その他のツール

いいえ、ツールをコンパイルしたりインストールしたりせずに、サーバーからCSVを取り出したいだけです。


1
結果はどこに保存されますか?クエリは実行されますが、ファイルがコンピュータのどこにも表示されません。これは私がやっていることです:COPY(cからa、bを選択します。ここでd = '1')。CSVHEADER> abcd.csvで標準出力するには
kRazzy R

1
@kRazzyR出力はpsqlコマンドのstdoutに送られるので、最終的にはstdoutで行うことは何でもデータが送られます。私の例では、「> file.csv」を使用してファイルにリダイレクトします。これが、psql -cパラメータを介してサーバーに送信されるコマンドの範囲外であることを確認したい場合。「ローカルマシン」の例を参照してください。
joshperry

1
完全な説明をありがとう。copyコマンドは、psqlで絶望的に複雑です。私は通常、無料のデータベースクライアント(dbeaverコミュニティエディション)を使用してデータファイルをインポートおよびエクスポートします。それは素晴らしいマッピングとフォーマットツールを提供します。あなたの答えは、リモートシステムからコピーするための非常に詳細な例を提供します。
Rich Lysakowski博士号

24

エラーメッセージが表示されたため、\ COPYを使用する必要がありました。

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

だから私は使用しました:

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

そしてそれは機能しています


17

psql あなたのためにこれを行うことができます:

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 psqlここで使用されるオプションのヘルプについては、を参照してください。


12
これは本当のCSVファイルではありません。データにカンマがある場合は書き込まれるので、組み込みのCOPYサポートを使用することをお勧めします。しかし、この一般的な手法は、CSV以外の他の区切り形式でPostgresからエクスポートするための迅速なハックとして便利です。
グレッグ・スミス

17

新しいバージョン-psql 12-がサポートされ--csvます。

psql-開発

--csv

CSV(コンマ区切り値)出力モードに切り替えます。これは、\ pset形式のcsvと同等です


csv_fieldsep

CSV出力形式で使用するフィールドセパレータを指定します。区切り文字がフィールドの値に含まれている場合、そのフィールドは標準のCSVルールに従って二重引用符で囲まれて出力されます。デフォルトはコンマです。

使用法:

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

このCOPY TO機能をサポートしていないAWS Redshiftに取り組んでいます。

しかし、私のBIツールはタブ区切りのCSVをサポートしているので、以下を使用しました。

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

11

pgAdmin IIIには、クエリウィンドウからファイルにエクスポートするオプションがあります。メインメニューで、[クエリ]-> [ファイルに実行]か、同じことを実行するボタンがあります(クエリを実行するだけの単純な緑色の三角形ではなく、青いフロッピーディスクのある緑色の三角形です)。クエリウィンドウからクエリを実行していない場合は、IMSOPの提案に従ってcopyコマンドを使用します。


特権管理者になる必要があるため、IMSoPの回答はうまくいきませんでした。これは御馳走を働いた。ありがとう!
Mike

9

私はいくつかのことを試しましたが、それらのいくつかは、ヘッダーの詳細を含む希望のCSVを提供することができませんでした。

ここに私のために働いたものがあります。

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

9

と呼ばれる小さなツールを書いた psql2csvCOPY query TO STDOUTパターンをカプセル化して、適切なCSVを生成。インターフェースはに似ていpsqlます。

psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY

クエリは、STDIN(存在する場合)の内容、または最後の引数と見なされます。これら以外のすべての引数は、psqlに転送されます。

-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
よく働く。ありがとうございました。
AlexM 2017年

6

クエリが長く、psqlを使用したい場合は、クエリをファイルに入れて、次のコマンドを使用します。

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

FWIW、MS Excelで正しく開くCSVファイルを生成する-F","代わりに使用する必要があり-F";"ました
CFL_Jeff

4

HEADERとして列名を含むCSVファイルをダウンロードするには、次のコマンドを使用します。

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

1

JetBrainsによるデータベースIDEであるDataGripを強くお勧めします。SQLクエリをCSVファイルにエクスポートできますに SSHトンネリングを簡単に設定できます。ドキュメントが「結果セット」に言及する場合、それらはコンソールのSQLクエリによって返される結果を意味します。

私はDataGripに関連付けられていません。製品が大好きです。


反対票はコンテキスト/説明の欠如が原因だったと思いますので、DataGripのドキュメントにリンクしました。反対票の理由が他にもある場合は、お知らせください。私は上記のCLIソリューションを使用しており、DataGripは小さなクエリに対してはるかに簡単です。
skeller88

DataGripの問題は、ウォレットがグリップされることです。無料ではありません。dbeaver.ioでDBeaverのコミュニティエディションをお試しください。これは、SQLプログラマー、DBA、アナリスト向けのFOSSマルチプラットフォームデータベースツールであり、MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL Server、Sybase、MS Access、Teradata、Firebird、Hive、Prestoなどの一般的なデータベースをすべてサポートしています。
Rich Lysakowski PhD

クールにチェックします。あなたのコメントも回答として再投稿してみませんか?
skeller88

0

WebブラウザーのデータベースクライアントであるJackDBは、これを非常に簡単にします。特にHerokuを使用している場合。

リモートデータベースに接続し、SQLクエリを実行できます。

                                                                                                                                                       ソース (ソース:jackdb.comjackdb-heroku


DBが接続されたら、クエリを実行してCSVまたはTXTにエクスポートできます(右下を参照)。


jackdb-export

注:私はJackDBとは一切関係ありません。私は現在彼らの無料サービスを利用しており、素晴らしい製品だと思います。


0

@ skeller88のリクエストに従って、すべての応答を読まない人に見失われないように、コメントを回答として再投稿しています...

DataGripの問題は、ウォレットがグリップされることです。無料ではありません。dbeaver.ioでDBeaverのコミュニティエディションをお試しください。これは、SQLプログラマー、DBA、アナリスト向けのFOSSマルチプラットフォームデータベースツールであり、MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL Server、Sybase、MS Access、Teradata、Firebird、Hive、Prestoなどの一般的なデータベースをすべてサポートしています。

DBeaver Community Editionを使用すると、データベースに接続し、クエリを発行してデータを取得し、結果セットをダウンロードしてCSV、JSON、SQL、またはその他の一般的なデータ形式で保存できます。TOAD for Postgres、TOAD for SQL Server、またはToad for Oracleの実行可能なFOSSライバルです。

私はDBeaverとは関係ありません。価格と機能は気に入っていますが、DBeaver / Eclipseアプリケーションをさらに開き、分析ウィジェットをDBeaver / Eclipseに簡単に追加できるようにしたいと思います。ユーザーが年間サブスクリプションに料金を支払ってグラフやチャートを直接作成する必要はありません。アプリケーション。私のJavaコーディングスキルは錆びており、Eclipseウィジェットの構築方法を再学習するのに何週間もかかるような気がしません。DBeaverがサードパーティのウィジェットをDBeaver Community Editionに追加する機能を無効にしていることに気づくだけです。

DBeaverのCommunity Editionに追加する分析ウィジェットを作成する手順について、DBeaverユーザーは洞察力がありますか?


-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
あなたが編集した答えを説明してください。コードのみの回答は避けてください
GGO

3
このコードスニペットをありがとうございます。このコードスニペットは、限られた短期間のヘルプを提供する可能性があります。適切な説明は、なぜこれが問題の優れた解決策であるを示すことにより、長期的な価値を大幅に改善し、他の同様の質問を持つ将来の読者にとってさらに役立つでしょう。答えを編集して、仮定を含めて説明を追加してください。
Toby Speight 2018

2
これにより、csvファイルではなくjsonファイルが生成されます。
nvoigt 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.