如何为psql动态创建输出文件

how to dynamically create an output file for psql

我有一个 SQL 脚本,将用于在数据库中进行更改。出于审计和可追溯性原因,我希望脚本根据 DBNAME 和时间戳生成输出文件名。

db_test=> select 'script_output-' || :'DBNAME' || '-' ||
 to_char(now(),'yyyymmdd-HH24MISS') || '.txt' as spoolfile;
                 spoolfile
--------------------------------------------
 script_output-db_test-20190718-163936.txt

但是,当我尝试将查询结果分配给 \out 运算符时,我得到以下结果

db_test=> \out select 'script_output-' || :'DBNAME' || '-' || to_char(now(),'yyyymmdd-HH24MISS') || '.txt'
\out: extra argument "script_output-" ignored
\out: extra argument "||" ignored
\out: extra argument ":'DBNAME'" ignored
\out: extra argument "||" ignored
\out: extra argument "-" ignored
\out: extra argument "||" ignored
\out: extra argument "to_char(now(),yyyymmdd-HH24MISS)" ignored
\out: extra argument "||" ignored
\out: extra argument ".txt" ignored

实际创建的输出文件名为 select

SDV184022L:~ myuser$ ls -la Downloads/DB-Install/sele*
-rw-r--r--  1 myuser  myuser     0B Jul 18 11:42 Downloads/DB-Install/select

根据这些结果和大量搜索,我假设这是不可能的,所以有人有其他方法来完成为输出指令生成动态文件名吗?

您可以使用 psql 变量通过 运行 中的 psql 命令存储查询结果。

knayak=# \set v_spoolfile `psql -A -t -c "select 'script_output-' ||  current_database() || '-' ||to_char(now(),'yyyymmdd-HH24MISS') || '.txt' as spoolfile" yourdbname`
knayak=# \echo :v_spoolfile
script_output-knayak-20190718-225537.txt
knayak=# \out :v_spoolfile

查询生成的结果可以使用 \gset 传输到 psql 中的 auto-instantiated 个变量。变量的名称是列的名称。尝试

db_test=> select 'script_output-' || :'DBNAME' || '-' ||
 to_char(now(),'yyyymmdd-HH24MISS') || '.txt' as spoolfile
 \gset

那你可以做

db_test=> \out :spoolfile

请注意,变量是用 "macro" 种扩展处理的。因此,如果 :spoolfile 的值恰好包含空格或反斜杠,psql 会将它们解释为就好像它们是在命令行上输入的一样。