将PL/pgSQL输出从PostgreSQL保存到CSV文件

将PL/pgSQL输出从PostgreSQL数据库保存到CSV文件的最简单方法是什么?

我正在使用PostgreSQL 8.4和pgAdmin III以及运行查询的PSQL插件。

863604 次浏览

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.022009-10-02,IEF,92.772009-10-02,IEV,37.052009-10-02,IJH,66.182009-10-02,IJR,50.332009-10-02,ILF,42.242009-10-02,INTC,18.972009-10-02,IP,21.39edd@ron:~$

有关此处使用的选项的帮助,请参阅man psql

您希望生成的文件在服务器上还是在客户端上?

服务端

如果你想要一些易于重用或自动化的东西,你可以使用Postgresql的内置复制命令。

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

这种方法完全在远程服务器上运行-它不能写入您的本地PC。它还需要作为Postgres“超级用户”(通常称为“root”)运行,因为Postgres无法阻止它对该机器的本地文件系统进行恶意操作。

这并不意味着您必须作为超级用户进行连接(自动化将是另一种安全风险),因为您可以使用#0选项到#1来创建就好像你是个超级用户的函数。

关键的部分是你的函数在那里执行额外的检查,而不仅仅是绕过安全性-所以你可以编写一个导出你需要的确切数据的函数,或者你可以编写一些可以接受各种选项的东西,只要它们符合严格的白名单。

  1. 应该允许用户在磁盘上读/写哪个文件?例如,这可能是一个特定的目录,并且文件名可能必须有合适的前缀或扩展名。
  2. 用户应该能够在数据库中读/写哪个?这通常由数据库中的GRANT定义,但是该函数现在作为超级用户运行,因此通常是“越界”的表将完全可访问。你可能不想让别人调用你的函数并在你的“用户”表的末尾添加行……

我已经编写了一篇博客文章扩展了这种方法,包括一些导出(或导入)满足严格条件的文件和表的函数示例。


客户端

另一种方法是在客户端进行文件处理,即在您的应用程序或脚本中。Postgres服务器不需要知道您要复制到哪个文件,它只是吐出数据,客户端将其放在某个地方。

这方面的底层语法是COPY TO STDOUT命令,像pgAdmin这样的图形工具将在一个漂亮的对话框中为您包装它。

#0命令行客户端有一个名为#1的特殊“元命令”,它采用与“真正的”COPY相同的所有选项,但在客户端内运行:

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

请注意,没有终止;,因为元命令由换行符终止,与SQL命令不同。

的文档

不要将COPY与psql指令\Copy混淆。\Copy调用COPY from STDIN或COPY TO STDOUT,然后将数据获取/存储在psql客户端可访问的文件中。因此,使用\Copy时,文件可访问性和访问权限取决于客户端而不是服务器。

您的应用程序编程语言可能也支持推送或获取数据,但您通常不能在标准SQL语句中使用COPY FROM STDIN/TO STDOUT,因为无法连接输入/输出流。PHP的PostgreSQL处理程序(没有 PDO)包括非常基本的#2#3函数,它们复制到/从PHP数组复制,这对于大型数据集可能无效。

在pgAdmin III中,有一个选项可以从查询窗口导出到文件。在主菜单中,它是查询->执行到文件,或者有一个按钮可以做同样的事情(它是一个带有蓝色软盘的绿色三角形,而不是仅仅运行查询的普通绿色三角形)。如果你没有从查询窗口运行查询,那么我会按照IMSoP的建议做并使用复制命令。

在终端(连接到数据库时)设置输出到cvs文件

1)将字段分离器设置为','

\f ','

2)设置输出格式不对齐:

\a

3)只显示元组:

\t

4)设置输出:

\o '/tmp/yourOutputFile.csv'

5)执行您的查询:

:select * from YOUR_TABLE

6)输出:

\o

然后,您将能够在此位置找到您的csv文件:

cd /tmp

使用scp命令复制它或使用nm进行编辑:

nano /tmp/yourOutputFile.csv

有几种解决方案:

1psql命令

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

这有一个很大的优势,你可以通过SSH使用它,比如ssh postgres@host command-使你能够获得

2 postgrescopy命令

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

3 psql交互式(或不)

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

所有这些都可以在脚本中使用,但我更喜欢#1。

4 pgadmin,但这不是脚本化的。

如果您对特定表的列以及标题所有感兴趣,您可以使用

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

这是一个稍微简单一点比

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

据我所知,这是相当的。

我正在使用AWS RedShift,它不支持COPY TO功能。

我的BI工具支持制表符分隔的CSV,所以我使用了以下内容:

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

JackDB,您的Web浏览器中的数据库客户端,使这变得非常容易。特别是如果您使用Heroku。

它允许您连接到远程数据库并对其运行SQL查询。

 ;来源jackdb-heroku
(来源:jackdb.com


连接数据库后,您可以运行查询并导出到CSV或TXT(见右下角)。


jackdb导出

注意:我与JackDB没有任何关系。我目前使用他们的免费服务,并认为这是一个很棒的产品。

我不得不使用\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;

而且还在运作

如果您有更长的查询并且您喜欢使用psql,则将查询放入文件并使用以下命令:

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

我编写了一个名为#0的小工具,它封装了COPY query TO STDOUT模式,从而产生了正确的CSV。它的界面类似于psql

psql2csv [OPTIONS] < QUERYpsql2csv [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
import jsoncursor = 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'

我尝试了几件事,但很少有人能够给我所需的CSV标题细节。

这是什么为我工作。

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

CSV导出统一

这些信息并没有很好地表达出来。因为这是我第二次需要推导出这个,所以我把它放在这里提醒自己,如果没有别的。

实际上,最好的方法(从postgres中获取CSV)是使用COPY ... TO STDOUT命令。尽管您不想按照此处答案中显示的方式执行。使用该命令的正确方法是:

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

记住一个命令!

它非常适合在ssh上使用:

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

它非常适合在docker over ssh中使用:

$ 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隧道更复杂,但对于其他输出格式(二进制),通过隧道连接执行本地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。

要下载列名称为HEADER的CSV文件,请使用以下命令:

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

新版本psql 12将支持--csv

psql-devel

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

根据@skeller88的要求,我正在转发我的评论作为一个答案,这样它就不会被那些没有阅读每一个回复的人丢失。

DataGrip的问题在于它会控制您的钱包。它不是免费的。请尝试DBeaver社区版dbeaver.io.它是一个FOSS多平台数据库工具,适用于SQL程序员,DBA和分析师,支持所有流行的数据库:MySQL,PostgreSQL,SQLite,Oracle,DB2,SQLServer,赛贝斯,MS Access,Teradata,Firebird,Hive,Presto等。

DBeaver Community Edition使连接到数据库、发出查询以检索数据,然后下载结果集以将其保存为CSV、JSON、SQL或其他常见数据格式变得轻而易举。它是TOAD for Postgres、TOAD forSQLServer或Toad for Oracle的一个可行的FOSS竞争对手。

我和DBeaver没有任何关系。我喜欢它的价格和功能,但我希望他们能更多地开放DBeaver/Eclipse应用程序,并使向DBeaver/Eclipse添加分析小部件变得容易,而不是要求用户支付年度订阅费用,直接在应用程序中创建图形和图表。我的Java编码技能生疏了,我不想花几周时间重新学习如何构建Eclipse小部件,却发现DBeaver已经禁用了向DBeaver社区版添加第三方小部件的能力。

DBeaver用户是否了解创建分析小部件以添加到DBeaver社区版的步骤?

从Postgres 12开始,您可以更改输出格式:

\pset format csv

允许以下格式:

aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped

如果要导出请求的结果,可以使用\o filename功能。

示例:

\pset format csv
\o file.csvSELECT * FROM table LIMIT 10;\o
\pset format aligned