【问题标题】:psql - read SQL file and output to CSVpsql - 读取 SQL 文件并输出到 CSV
【发布时间】:2021-03-05 02:23:23
【问题描述】:

我有一个 SQL 文件my_query.sql:

select * from my_table

使用psql,我可以读取这个sql文件:

\i my_query.sql

或者将其作为 arg 传入:

psql -f my_query.sql

我可以将查询字符串的结果输出到 csv:

\copy (select * from my_table) to 'output.csv' with csv header

有没有办法将这些组合起来,以便我可以将查询结果从 SQL 文件输出到 CSV?

【问题讨论】:

  • 你有什么尝试吗?
  • 什么都没有。
  • 您的意思类似于从命令行运行:psql -f my_query.sql -d mydb 其中my_query.sql 包含您的 COPY 语句?
  • no @KristoMagi SQL 查询只是一个普通的旧查询,没有任何 copy 语法。
  • 您使用的是哪个操作系统?

标签: postgresql psql


【解决方案1】:

不幸的是,没有内置的功能,所以你需要一点 bash-fu 才能让它正常工作。

CONN="psql -U my_user -d my_db"
QUERY="$(sed 's/;//g;/^--/ d;s/--.*//g;' my_query.sql | tr '\n' ' ')"

echo "\\copy ($QUERY) to 'out.csv' with CSV HEADER" | $CONN

sed fun 删除了所有分号、注释行和行尾 cmets,tr 将换行符转换为空格(如 @abelisto 的评论中所述):

-- my_query.sql
select *
from my_table
where timestamp < current_date -- only want today's records
limit 10;

变成:

select * from my_table where timestamp < current_date limit 10

然后将其传递给有效的psql 命令:

\copy (select * from my_table where timestamp < current_date) to 'out.csv' with csv header

这是一个脚本:

sql_to_csv.sh

#!/bin/bash
# sql_to_csv.sh

CONN="psql -U my_user -d my_db"
QUERY="$(sed 's/;//g;/^--/ d;s/--.*//g;' $1 | tr '\n' ' ')"
echo "$QUERY"

echo "\\copy ($QUERY) to '$2' with csv header" | $CONN > /dev/null

./sql_to_csv.sh my_query.sql out.csv

【讨论】:

    【解决方案2】:

    您可以使用 bash 脚本来完成。

    dump_query_to_csv.sh:

    #!/bin/bash
    
    # Takes an sql query file as an argument and dumps its results
    # to a CSV file using psql \copy command.
    #
    # Usage:
    #
    #  dump_query_to_csv.sh <sql_query_file> [<csv_output_filesname>]
    
    SQL_FILE=$1
    [ -z $SQL_FILE ] && echo "Must supply query file" && exit
    shift
    
    OUT_FILE=$1
    [ -z $OUT_FILE ] && OUT_FILE="output.csv" # default to "output.csv" if no argument is passed
    
    TMP_TABLE=ttt_temp_table_xx # some table name that will not collide with existing tables
    
    ## Build a psql script to do the work
    PSQL_SCRIPT=temp.psql
    
    # create a temporary database table using the SQL from the query file
    echo "DROP TABLE IF EXISTS $TMP_TABLE;CREATE TABLE $TMP_TABLE AS" > $PSQL_SCRIPT
    cat $SQL_FILE >> $PSQL_SCRIPT
    echo ";" >> $PSQL_SCRIPT
    
    # copy the temporary table to the output CSV file
    echo "\copy (select * from $TMP_TABLE) to '$OUT_FILE' with csv header" >> $PSQL_SCRIPT
    
    # drop the temporary table
    echo "DROP TABLE IF EXISTS $TMP_TABLE;" >> temp.sql
    
    ## Run psql script using psql
    psql my_database < $PSQL_SCRIPT # replace my_database and add user login credentials as necessary
    
    ## Remove the psql script
    rm $PSQL_SCRIPT
    

    您需要编辑脚本中的psql 行以连接到您的数据库。还可以增强脚本以将数据库和帐户凭据作为参数。

    【讨论】:

    • 我更喜欢@Abelisto 的解决方案,如果它有效的话。我认为他应该把它作为一个答案,而不是评论。
    【解决方案3】:

    接受的解决方案是正确的,但我有 Windows 并且必须通过批处理(命令)文件使其运行。如果有人需要,请在此处发布

    @echo off
    
    echo 'Reading file %1'
    set CONN="C:\Program Files\PostgreSQL\11\bin\psql.exe" -U dbusername -d mydbname
    "C:\Program Files\Git\usr\bin\sed.exe" 's/;//g;/^--/ d;s/--.*//g;' %1 | "C:\Program Files\Git\usr\bin\tr.exe" '\n' ' ' > c:\temp\query.txt
    set /p QUERY=<c:\temp\query.txt
    echo %QUERY%
    
    echo \copy (%QUERY%) to '%2' WITH (FORMAT CSV, HEADER) | %CONN%
    

    【讨论】:

      【解决方案4】:

      我认为最简单的方法是利用shell的变量扩展能力:

      psql -U my_user -d my_db -c "COPY ($(cat my_query.sql)) TO STDOUT WITH CSV HEADER" > my_query_results.csv
      

      【讨论】:

      • 在 OSX 中尝试此操作时,我得到“在“$”处或附近出现语法错误。
      • 请注意,当我尝试此操作时,我在 psql 命令行。
      猜你喜欢
      • 1970-01-01
      • 2015-08-07
      • 2019-08-17
      • 1970-01-01
      • 2017-09-14
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      相关资源
      最近更新 更多