Bash脚本循环数组执行PostgreSQL查询导出失败求助
解决Bash循环结合psql HERE文档的执行问题
你遇到的核心问题是把Bash的循环逻辑放到了PostgreSQL的HERE文档(EOF块)内部——psql只识别SQL和自身的元命令(比如\COPY),完全看不懂Bash的declare、for这些语法,所以整个脚本执行时会报错,循环自然无法正常运行。当你移除循环语句后,剩下的是纯psql可识别的命令,所以能正常工作。
下面是修正后的脚本,同时我会标注几个关键的修改点:
dbname="XXX" username="XXXXX" # 修正Bash数组的写法:元素之间用空格分隔,不需要逗号 declare -a arr=('MFR' 'PQR' 'REV') # 把循环逻辑放在HERE文档外部,由Bash处理迭代 for i in "${arr[@]}" do psql "$dbname" "$username" << EOF \COPY ( SELECT d.woyhh, COALESCE(ct.ct, 0) AS total_count FROM ( SELECT f_woyhh(d::TIMESTAMP) AS woyhh FROM generate_series(TIMESTAMP '2018-01-01', TIMESTAMP '2018-12-31', interval '1 hour') d ) d LEFT JOIN ( SELECT f_woyhh((TIME)::TIMESTAMP) AS woyhh, count(*) AS ct FROM counties c JOIN ltg_data d ON ST_contains(c.the_geom, d.ltg_geom) WHERE cwa = '$i' -- 用单引号包裹变量,符合SQL字符串语法要求 GROUP BY 1 ) ct USING (woyhh) -- 修正了原查询中的笔误:whh → woyhh ORDER BY 1 ) TO '/var/www/html/GIS/ltg_db/bigquery/hourly_$i.csv' CSV HEADER; EOF done
关键修改说明:
- Bash数组语法修正:原数组写法里的逗号是多余的,Bash数组元素之间直接用空格分隔即可,否则会把逗号当成元素的一部分,导致查询时
cwa值错误。 - 循环逻辑移至外部:让Bash负责遍历数组,每次迭代生成独立的psql调用,这样变量
$i会被Bash正确替换为当前的地理区域代码,再传递给psql执行。 - SQL字符串变量包裹:
WHERE cwa = '$i'中的单引号必须保留,因为cwa是字符串类型字段,没有单引号会触发SQL语法错误,同时也能避免简单的SQL注入风险。 - 修复查询笔误:原查询中
USING (whh)是错误的,应该和前面的woyhh列名保持一致,否则会因列名不匹配导致查询失败。 - 导出路径加单引号:把CSV文件路径用单引号包裹,避免路径中如果出现特殊字符(比如空格)时出现解析错误。
这样修改后,脚本会逐个处理每个地理区域,执行对应的查询并导出到命名正确的CSV文件中,循环可以正常工作。
内容的提问来源于stack exchange,提问作者user1610717
相关产品推荐
相关产品推荐

