从PostgreSQL数据库保存PL/pgSQL输出到CSV文件的最简单的方法是什么?
我使用PostgreSQL 8.4 pgAdmin III和PSQL插件,我从那里运行查询。
从PostgreSQL数据库保存PL/pgSQL输出到CSV文件的最简单的方法是什么?
我使用PostgreSQL 8.4 pgAdmin III和PSQL插件,我从那里运行查询。
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。
您希望生成的文件在服务器上还是客户机上?
服务器端
如果你想要一些易于重用或自动化的东西,你可以使用Postgresql内置的COPY命令。如。
Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;
这种方法完全运行在远程服务器上-它不能写入您的本地PC。它还需要作为Postgres的“超级用户”(通常称为“root”)运行,因为Postgres无法阻止它对机器的本地文件系统做一些讨厌的事情。
这实际上并不意味着您必须以超级用户的身份连接(自动化这将是另一种安全风险),因为您可以使用CREATE FUNCTION的security DEFINER选项来创建一个像超级用户一样运行的函数。
关键的部分是你的函数要执行额外的检查,而不仅仅是绕过安全性——所以你可以编写一个函数来导出你需要的确切数据,或者你可以编写一些东西,只要它们符合严格的白名单,就可以接受各种选项。你需要检查两件事:
Which files should the user be allowed to read/write on disk? This might be a particular directory, for instance, and the filename might have to have a suitable prefix or extension. Which tables should the user be able to read/write in the database? This would normally be defined by GRANTs in the database, but the function is now running as a superuser, so tables which would normally be "out of bounds" will be fully accessible. You probably don’t want to let someone invoke your function and add rows on the end of your “users” table…
我已经写了一篇关于这种方法的博客文章,包括一些函数的例子,导出(或导入)满足严格条件的文件和表。
客户端
另一种方法是在客户端进行文件处理,即在应用程序或脚本中。Postgres服务器不需要知道你要复制到哪个文件,它只是吐出数据,然后客户端把它放在某个地方。
它的底层语法是COPY TO STDOUT命令,像pgAdmin这样的图形化工具将为您在一个漂亮的对话框中包装它。
psql命令行客户端有一个特殊的“元命令”,称为\copy,它与“真正的”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)包括非常基本的pg_copy_from和pg_copy_to函数,用于从PHP数组中复制或从数组中复制,这对于大型数据集可能不太有效。
在pgAdmin III中,有一个从查询窗口导出到文件的选项。在主菜单中,它是Query -> Execute to file或者有一个按钮做同样的事情(它是一个带有蓝色软盘的绿色三角形,而不是仅仅运行查询的普通绿色三角形)。如果您没有从查询窗口运行查询,那么我将按照IMSoP的建议使用复制命令。
在终端(当连接到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
有几种解决方案:
1 PSQL命令
psql -d dbname -t -A -F"," -c "select * from users" > output.csv
这有一个很大的优势,您可以通过SSH使用它,如SSH postgres@host命令-使您能够获得
2 postgres copy命令
拷贝(SELECT * from users)到'/tmp/output.csv'
PSQL交互(或不交互)
>psql dbname
psql>\f ','
psql>\a
psql>\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红移,它不支持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.com)
一旦连接了数据库,就可以运行查询并导出到CSV或TXT(见右下角)。
注:我与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
我写了一个叫做psql2csv的小工具,它封装COPY查询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
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'
我尝试了几件事,但很少有人能够给我所需的CSV与头细节。
以下是对我有效的方法。
psql -d dbame -U username \
-c "COPY ( SELECT * FROM TABLE ) TO STDOUT WITH CSV HEADER " > \
OUTPUT_CSV_FILE.csv
CSV统一导出
这个信息并没有很好地表示出来。因为这是我第二次需要推导这个,我把它写在这里提醒自己。
实际上,最好的方法(从postgres中获取CSV)是使用COPY…到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中使用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可以作为执行it1的用户在psql命令运行的任何系统上有效地执行文件操作。如果连接到远程服务器,那么将执行psql的系统上的数据文件复制到远程服务器或从远程服务器复制数据文件是很简单的。
COPY作为后端进程用户帐户(默认为postgres)在服务器上执行文件操作,检查并相应应用文件路径和权限。如果使用TO STDOUT,则绕过文件权限检查。
如果psql没有在您希望生成的CSV最终驻留的系统上执行,这两个选项都需要后续的文件移动。根据我的经验,当您主要使用远程服务器时,这是最可能的情况。
通过ssh配置TCP/IP隧道之类的东西到远程系统以获得简单的CSV输出会更复杂,但对于其他输出格式(二进制),最好通过隧道连接/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。
下载列名为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 .io上试试社区版的DBeaver。它是一个面向SQL程序员、dba和分析师的自由/开源多平台数据库工具,支持所有流行的数据库:MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL Server、Sybase、MS Access、Teradata、Firebird、Hive、Presto等。
DBeaver Community Edition使得连接到数据库、发出查询以检索数据、然后下载结果集以将其保存为CSV、JSON、SQL或其他常见数据格式变得非常简单。对于Postgres的TOAD, SQL Server的TOAD,或者Oracle的TOAD,它是一个可行的自由/开源软件竞争对手。
I have no affiliation with DBeaver. I love the price and functionality, but I wish they would open up the DBeaver/Eclipse application more and made it easy to add analytics widgets to DBeaver / Eclipse, rather than requiring users to pay for the annual subscription to create graphs and charts directly within the application. My Java coding skills are rusty and I don't feel like taking weeks to relearn how to build Eclipse widgets, only to find that DBeaver has disabled the ability to add third-party widgets to the DBeaver Community Edition.
DBeaver用户是否了解如何创建要添加到社区版的分析小部件?
从Postgres 12开始,你可以改变输出格式:
\pset format csv
允许使用以下格式:
aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped
如果要导出请求的结果,可以使用\o文件名特性。
例子:
\pset format csv
\o file.csv
SELECT * FROM table LIMIT 10;
\o
\pset format aligned