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

我使用PostgreSQL 8.4 pgAdmin III和PSQL插件,我从那里运行查询。


当前回答

我不得不使用\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可以帮你做到这一点:

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数组中复制或从数组中复制,这对于大型数据集可能不太有效。

在终端(当连接到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,因为我收到了错误消息:

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

所以我用了:

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

它在运作