Bash psql查询文件中是否可能出现换行?
我正在运行一个bash文件来处理一些psql任务。但是,我希望包含查询的文本文件(fp_query.txt)接受换行,以增强可读性。目前,我遇到以下错误:Bash psql查询文件中是否可能出现换行?,bash,psql,Bash,Psql,我正在运行一个bash文件来处理一些psql任务。但是,我希望包含查询的文本文件(fp_query.txt)接受换行,以增强可读性。目前,我遇到以下错误: parse error at end of line 当我保持换行时。有没有办法让解释器忽略换行符,以便我可以将它们保存在查询文件中 以下是.sh文件供参考: export PGPASSFILE=.pgpass psql -h [hostname] -d [dbname] -U [user] -f fp_query.txt 下面是fp_q
parse error at end of line
当我保持换行时。有没有办法让解释器忽略换行符,以便我可以将它们保存在查询文件中
以下是.sh文件供参考:
export PGPASSFILE=.pgpass
psql -h [hostname] -d [dbname] -U [user] -f fp_query.txt
下面是fp_query.txt:
\copy (SELECT created_at::date, COUNT(*)
FROM ela_snapshots
WHERE created_at::date > CURRENT_DATE - 30
GROUP BY 1) to 'ELA_comp_tot_daily_sess.csv' with CSV HEADER
问题不在于查询文件中有换行符,而在于
\copy
元命令中有换行符。根据:
对参数的分析会在行尾停止,或者在找到另一个不带引号的反斜杠时停止。未加引号的反斜杠作为新元命令的开头。特殊序列\\
(两个反斜杠)标记参数的结束,并继续解析SQL命令(如果有)。这样,SQL和psql命令可以在一行中自由混合。但在任何情况下,元命令的参数都不能超过行尾
(我的重点)。如果在交互式psql
提示符下运行此命令,则同样如此
一种解决方法可能是,让您的\copy
元命令运行一个只调用该函数的查询。直接回答和解决方案
如中所述,PostgreSQL元命令必须占用一行。我通过为\copy
创建一个临时表来解决这个问题
文件的快速转换,fp_query.txt
,如下所示
CREATE TEMP TABLE "temp_unique_name" AS
SELECT created_at::date, COUNT(*)
FROM ela_snapshots
WHERE created_at::date > CURRENT_DATE - 30
GROUP BY 1;
\copy "temp_uniq_name" to 'ELA_comp_tot_daily_sess.csv' with CSV HEADER
CREATE TEMP TABLE ":table_name" AS
[...query...]
\copy ":table_name" to 'ELA_comp_tot_daily_sess.csv' with CSV HEADER
<>你可能会考虑其他改进。
补充讨论
临时表的随机名称
您不太可能遇到表名冲突,但是,同样,通过创建一个随机名称来避免它们非常简单
SELECT 'tmp_' || (RANDOM()*1e15)::INT8 AS table_name
\gset
。。。用这个名字
CREATE TEMP TABLE "temp_unique_name" AS
SELECT created_at::date, COUNT(*)
FROM ela_snapshots
WHERE created_at::date > CURRENT_DATE - 30
GROUP BY 1;
\copy "temp_uniq_name" to 'ELA_comp_tot_daily_sess.csv' with CSV HEADER
CREATE TEMP TABLE ":table_name" AS
[...query...]
\copy ":table_name" to 'ELA_comp_tot_daily_sess.csv' with CSV HEADER
请注意以下关于此处使用的psql特性的内容
meta命令在缓冲区中运行查询,并将非空值设置为与列别名类似的变量。有关详细信息,请查找\gset
重要的是,请注意查询不会以分号结尾,因为这会立即执行缓冲区\gset
- 与所有的
变量一样,由psql
创建的变量通过在变量名前加冒号来使用,如\gset
:table_name
的值应RANDOM()…
/转换为CAST
,以消除任何小数点,这在未引用的表名中会很麻烦,甚至在引用时也可能会混淆。这里,我使用了一个INT
(或者别名BIGINT
),因为我要乘以的系数很大INT8
只要使用<代码> \gSET/COD>创建表名,就可以考虑为输出创建动态文件名。
SELECT 'tmp_' || (RANDOM()*1e15)::INT8 AS table_name,
'ELA_comp_tot_' || to_char(CURRENT_TIMESTAMP, 'YYYYMMDD_HHMMSS') || '.csv' AS file_name
\gset
现在,您可以使用以下命令
\copy ":table_name" to ":file_name" with CSV HEADER
如前所述,这将输出到类似于ELA_comp_tot_20180404_142329.csv的内容。顺便说一下,.csv
扩展名不会改变输出,但更好地指示文件内容,尤其是基于GUI的文件系统界面
\copy
元命令的语法
如前所述,您的示例代码(为了避免混淆,我逐字复制了它)使用了9.0版之前的COPY
命令语法。使用较新的语法,它将如下所示:
\COPY ":table_name" TO ":file_name" WITH (FORMAT CSV, HEADER TRUE)
这是一个次要问题,因为9.x版仍然正式支持该语法。我喜欢大写关键字也没关系