1045

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

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

4

17 回答 17

1521

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

服务器端

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

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

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

这实际上并不意味着您必须以超级用户的身份进行连接(自动化这将是一种不同类型的安全风险),因为您可以使用SECURITY DEFINER选项来CREATE FUNCTION创建一个像超级用户一样运行的功能。

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

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

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


客户端

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

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

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

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

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

文档

不要将 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 数组复制的函数,这对于大型数据集可能效率不高。

于 2009-10-04T23:18:19.780 回答
597

有几种解决方案:

1 个psql命令

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 dbname
psql>\f ','
psql>\a
psql>\o '/tmp/output.csv'
psql>SELECT * from users;
psql>\q

它们都可以在脚本中使用,但我更喜欢#1。

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

于 2012-08-08T17:56:14.563 回答
102

In terminal (while connected to the db) set output to the cvs file

1) Set field seperator to ',':

\f ','

2) Set output format unaligned:

\a

3) Show only tuples:

\t

4) Set output:

\o '/tmp/yourOutputFile.csv'

5) Execute your query:

:select * from YOUR_TABLE

6) Output:

\o

You will then be able to find your csv file in this location:

cd /tmp

Copy it using the scp command or edit using nano:

nano /tmp/yourOutputFile.csv
于 2012-06-11T11:18:01.897 回答
52

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 最终驻留的系统上执行,这两个选项都需要后续文件移动。根据我的经验,当您主要使用远程服务器时,这是最有可能的情况。

将 TCP/IP 隧道通过 ssh 配置到远程系统以实现简单的 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。

于 2018-04-24T01:17:06.030 回答
40

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

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

这比简单一点

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

据我所知,这是等效的。

于 2013-01-11T20:34:59.287 回答
39

新版本 - 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
于 2018-12-08T12:47:21.387 回答
28

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

它正在运行

于 2014-06-28T21:41:00.017 回答
21

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

于 2009-10-04T23:12:13.733 回答
21

我正在研究不支持该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
于 2014-03-27T00:16:31.333 回答
12

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

于 2009-11-04T16:58:59.643 回答
10

我编写了一个名为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
于 2015-09-18T16:42:31.903 回答
10

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

这对我有用。

psql -d dbame -U username \
  -c "COPY ( SELECT * FROM TABLE ) TO STDOUT WITH CSV HEADER " > \
  OUTPUT_CSV_FILE.csv
于 2018-04-02T08:14:23.580 回答
9

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

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv
于 2014-09-18T19:52:49.073 回答
5

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

Copy (Select * From tableName) To '/tmp/fileName.csv' With CSV HEADER;
于 2018-11-30T08:25:24.917 回答
-2

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

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

                                                                                                                                                       来源 (来源:jackdb.comjackdb-heroku


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


jackdb 导出

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

于 2014-04-15T14:50:37.037 回答
-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'
于 2018-02-27T10:56:14.020 回答
-3

根据@skeller88 的要求,我将我的评论重新发布为答案,以免被不阅读所有回复的人迷失......

DataGrip 的问题在于它会控制你的钱包。它不是免费的。在 dbeaver.io 上试用 DBeaver 社区版。它是一款面向 SQL 程序员、DBA 和分析师的 FOSS 多平台数据库工具,支持所有流行的数据库:MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL Server、Sybase、MS Access、Teradata、Firebird、Hive、Presto 等。

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

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

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

于 2019-12-06T04:21:25.917 回答