关于sql:将PostgreSQL的PL / pgSQL输出保存到CSV文件

Save PL/pgSQL output from PostgreSQL to a CSV file

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

我使用的是PostgreSQL 8.4和pgadminIII和psql插件,在其中运行查询。


您想在服务器上还是在客户机上得到结果文件?

服务器端

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

1
Copy (SELECT * FROM foo) TO '/tmp/test.csv' WITH CSV DELIMITER ',';

这种方法完全在远程服务器上运行——它不能写入您的本地PC。它还需要以Postgres"超级用户"(通常称为"根")的身份运行,因为Postgres不能阻止它对该计算机的本地文件系统做令人讨厌的事情。

这并不意味着您必须作为超级用户连接(自动化这将是一种不同类型的安全风险),因为您可以使用CREATE FUNCTIONSECURITY DEFINER选项来创建一个像超级用户一样运行的函数。

关键的一点是,您的函数需要执行额外的检查,而不仅仅是绕过安全性,这样您就可以编写一个函数来导出所需的准确数据,或者编写一些可以接受各种选项的函数,只要它们符合严格的白名单。你需要检查两件事:

  • 允许用户在磁盘上读/写哪些文件?例如,这可能是一个特定的目录,文件名可能必须具有适当的前缀或扩展名。
  • 用户应该能够在数据库中读/写哪些表?这通常由数据库中的GRANT定义,但函数现在作为超级用户运行,因此通常"越界"的表将完全可访问。您可能不想让某人调用您的函数并在"用户"表的末尾添加行…
  • 我写了一篇关于这种方法的博客文章,其中包括一些导出(或导入)满足严格条件的文件和表的函数示例。

    客户端

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

    它的底层语法是COPY TO STDOUT命令,像pgadmin这样的图形工具将把它包装在一个很好的对话框中。

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

    1
    \copy (SELECT * FROM foo) TO '/tmp/test.csv' WITH CSV

    注意,不存在终止;,因为与SQL命令不同,meta命令是用换行符终止的。

    来自文档:

    Do not confuse COPY with the psql instruction \copy. \copy invokes COPY FROM STDIN or COPY TO STDOUT, and then fetches/stores the data in a file accessible to the psql client. Thus, file accessibility and access rights depend on the client rather than the server when \copy is used.

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


    有几种解决方案:

    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交互(或不交互)

    1
    2
    3
    4
    5
    6
    >psql dbname
    psql>\f ','
    psql>\a
    psql>\o '/tmp/output.csv'
    psql>SELECT * FROM users;
    psql>\q

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

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


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

    1)将字段分隔符设置为','

    1
    \f ','

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

    1
    \a

    3)仅显示元组:

    1
    \t

    4)设置输出:

    1
    \o '/tmp/yourOutputFile.csv'

    5)执行查询:

    1
    :SELECT * FROM YOUR_TABLE

    6)输出:

    1
    \o

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

    1
    cd /tmp

    使用scp命令复制或使用nano编辑:

    1
    nano /tmp/yourOutputFile.csv


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

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

    这比

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

    据我所知,这是等效的。


    我必须使用副本,因为我收到错误消息:

    1
    ERROR:  could NOT OPEN file"/filepath/places.csv" FOR writing: Permission denied

    所以我用:

    1
    \Copy (SELECT address, zip  FROM manjadata) TO '/filepath/places.csv' WITH CSV;

    而且它在起作用


    csv导出统一

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

    真正做到这一点(让csv离开postgres)的最好方法是使用COPY ... TO STDOUT命令。尽管你不想按照这里的答案来做。使用命令的正确方法是:

    1
    COPY (SELECT id, name FROM groups) TO STDOUT WITH CSV HEADER

    记住只有一个命令!

    它非常适合在ssh上使用:

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

    它非常适合在Docker内部通过ssh使用:

    1
    $ ssh pgserver.example.com 'docker exec -tu postgres postgres psql -d mydb -c"COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

    在本地机器上更是如此:

    1
    $ psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

    还是在本地机器上的Docker内部?:

    1
    docker EXEC -tu postgres postgres psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

    或者在kubernetes集群上,在docker中,通过https??

    1
    kubectl EXEC -t postgres-2592991581-ws2td 'psql -d mydb -c"COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

    多功能,多逗号!

    你还会吗?

    是的,我有,这是我的笔记:

    抄袭

    使用/copy可以有效地在运行psql命令的任何系统上执行文件操作,就像执行该命令的用户一样。如果连接到远程服务器,将执行psql的系统上的数据文件复制到远程服务器或从远程服务器复制数据文件很简单。

    COPY作为后端进程用户帐户(默认为postgres)在服务器上执行文件操作,文件路径和权限被相应地检查和应用。如果使用TO STDOUT,则跳过文件权限检查。

    如果psql没有在您希望结果csv最终驻留的系统上执行,这两个选项都需要随后的文件移动。根据我的经验,这是最有可能的情况,当您主要使用远程服务器时。

    为了简单的csv输出而将ssh上的TCP/IP隧道配置到远程系统更复杂,但是对于其他输出格式(二进制),通过隧道连接执行本地psql可能更好。同样,对于大型导入,将源文件移动到服务器并使用COPY可能是最高性能的选择。

    PSQL参数

    使用psql参数,您可以像csv一样格式化输出,但也有一些缺点,例如必须记住禁用寻呼机而不获取头:

    1
    2
    3
    4
    $ 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。


    psql可以为您做到:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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


    在pgadmin iii中,有一个选项可从查询窗口导出到文件。在主菜单中,它是query->execute to file,或者有一个按钮执行相同的操作(它是一个绿色三角形,带有蓝色软盘,而不是运行查询的普通绿色三角形)。如果您没有从查询窗口运行查询,那么我将按照imsop的建议执行,并使用copy命令。


    我正在研究AWS Redshift,它不支持COPY TO功能。

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

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

    新版本PSQL12将支持--csv

    psql - devel

    --csv

    Switches to CSV (Comma-Separated Values) output mode. This is equivalent to \pset format csv.

    csv_fieldsep

    Specifies the field separator to be used in CSV output format. If the separator character appears in a field's value, that field is output within double quotes, following standard CSV rules. The default is a comma.

    用途:

    1
    2
    3
    4
    5
    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

    我写了一个叫做psql2csv的小工具,它封装了COPY query TO STDOUT模式,从而产生了正确的csv。它的接口类似于psql

    1
    2
    psql2csv [OPTIONS] < QUERY
    psql2csv [OPTIONS] QUERY

    假设查询是stdin的内容(如果存在)或最后一个参数。所有其他参数都会转发到psql,除了:

    1
    2
    3
    -h, --help           show help, then exit
    --encoding=ENCODING  use a different encoding than UTF8 (Excel likes LATIN1)
    --no-header          do not output a header


    如果您有更长的查询,并且希望使用psql,那么将查询放到一个文件中,并使用以下命令:

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


    我尝试了几件事,但很少有人能给我想要的带标题细节的csv。

    这就是对我有用的。

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

    要下载以列名为标题的csv文件,请使用以下命令:

    1
    Copy (SELECT * FROM tableName) TO '/tmp/fileName.csv' WITH CSV HEADER;

    jackdb是Web浏览器中的一个数据库客户端,它使这一切变得非常简单。尤其是当你在Heroku的时候。

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

    &公司&nBSP来源jackdb heroku网站:http://static.jackdb.com/assets/img/blog/jackdb-heroku-oauth-connect.gif

    连接数据库后,可以运行查询并导出到csv或txt(请参见右下角)。

    jackdb-export

    注:我与JackDB没有任何关系。我现在使用他们的免费服务,认为这是一个伟大的产品。


    我强烈推荐Datagrip,JetBrains的数据库IDE。您可以将SQL查询导出到csv文件,并可以轻松设置ssh隧道。当文档提到"结果集"时,它们是指控制台中的SQL查询返回的结果。

    我没有与数据报关联,我只是喜欢这个产品!


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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'