将PostgreSQL的PL / pgSQL输出保存为CSV文件

时间:2009-10-04 22:58:51

标签: sql postgresql csv postgresql-copy

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

我正在使用带有pgAdmin III和PSQL插件的PostgreSQL 8.4来运行查询。

18 个答案:

答案 0 :(得分:1199)

您想要在服务器上还是在客户端上生成文件?

服务器端

如果您想要易于重用或自动化的东西,可以使用Postgresql的内置COPY命令。 e.g。

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

此方法完全在远程服务器上运行 - 它无法写入本地PC。它还需要作为Postgres“超级用户”(通常称为“root”)运行,因为Postgres无法阻止它使用该机器的本地文件系统做坏事。

这实际上并不意味着您必须以超级用户身份进行连接(自动化会产生不同类型的安全风险),因为您可以使用the SECURITY DEFINER option to CREATE FUNCTION创建运行的功能虽然你是超级用户

关键部分是你的功能是执行额外的检查,而不仅仅是绕过安全 - 所以你可以写一个导出你需要的确切数据的函数,或者你可以写一些可以接受各种选项的函数只要他们遇到严格的白名单。你需要检查两件事:

  1. 允许用户在磁盘上读/写哪个文件?例如,这可能是一个特定的目录,文件名可能必须有一个合适的前缀或扩展名。
  2. 用户应该能够在数据库中读/写哪些?这通常由数据库中的GRANT定义,但该函数现在以超级用户身份运行,因此通常“超出界限”的表将是完全可访问的。您可能不希望让某人调用您的函数并在“用户”表的末尾添加行...
  3. 我写过a blog post expanding on this approach,包括一些导出(或导入)符合严格条件的文件和表格的函数示例。


    客户端

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

    这个基础语法是COPY TO STDOUT命令,像pgAdmin这样的图形工具会在一个很好的对话框中为你包装它。

    psql命令行客户端有一个特殊的“元命令”,名为 \copy ,它采用的所有选项与“真实的”COPY,但是在客户端内运行:

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

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

    来自the docs

      

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

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

答案 1 :(得分:458)

有几种解决方案:

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 interactive(或不是)

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

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

4 pgadmin,但这不是可编写脚本的。

答案 2 :(得分:84)

在终端(连接到数据库时)将输出设置为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

答案 3 :(得分:34)

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

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

这比

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

据我所知,这是等效的。

答案 4 :(得分:22)

我必须使用\ 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;

它正在运作

答案 5 :(得分:22)

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

在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

如此多才多艺的逗号!

你甚至?

是的我做了,这是我的笔记:

COPYses

使用/copy可以在运行psql命令的任何系统上有效地执行文件操作,作为执行它的用户1。如果连接到远程服务器,则可以轻松地将执行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。

答案 6 :(得分:16)

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

答案 7 :(得分:12)

我正在使用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

答案 8 :(得分:11)

在pgAdmin III中,有一个从查询窗口导出到文件的选项。在主菜单中,它是查询 - >执行文件或有一个按钮执行相同的操作(它是一个带有蓝色软盘的绿色三角形,而不是只运行查询的普通绿色三角形)。如果您没有从查询窗口运行查询,那么我将执行IMSoP建议并使用复制命令。

答案 9 :(得分:8)

新版本-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

答案 10 :(得分:7)

我编写了一个名为psql2csv的小工具,它封装了COPY 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

答案 11 :(得分:6)

我尝试了几件事,但很少有人能够通过标题详细信息向我提供所需的CSV。

这对我有用。

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

答案 12 :(得分:5)

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

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

答案 13 :(得分:3)

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

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

答案 14 :(得分:1)

JackDB,Web浏览器中的数据库客户端,非常简单。特别是如果你在Heroku上。

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

Source jackdb-heroku http://static.jackdb.com/assets/img/blog/jackdb-heroku-oauth-connect.gif


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


jackdb-export

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

答案 15 :(得分: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用户是否了解创建添加到DBeaver社区版的分析小部件的步骤?

答案 16 :(得分:-1)

我强烈建议您使用DataGrip,这是JetBrains的数据库IDE。您可以export a SQL query to a CSV file,并且可以轻松设置ssh隧道。当文档中提到“结果集”时,它们表示控制台中SQL查询返回的结果。

我与DataGrip无关,我只是喜欢这个产品!

答案 17 :(得分:-3)

Year    Code
------------
2018    KK
2016    HH
2013    AA