【问题标题】:Why can't I use a variable in a postgres backslash command (\COPY)为什么我不能在 postgres 反斜杠命令 (\COPY) 中使用变量
【发布时间】:2021-10-07 20:43:18
【问题描述】:

我有以下 sql 脚本:

\COPY my_table (column_1, column_2) FROM :csv_file WITH (FORMAT CSV, DELIMITER ',', ESCAPE '"');

我打电话的来源:

psql -d $DB_NAME -f $SQL_FILE -v csv_file="$CSV_FILE"

但它一直在寻找一个名为“:csv_file”的文件。我做错了吗?

【问题讨论】:

  • 不是您问题的答案,但您也可以立即使用副本:psql -c '\COPY ...'
  • 谢谢。是的,这发生在更长的 sql BEGIN - COMMIT 中。
  • 我的猜测是你不能在那里使用变量,就像你不能在 SELECT 语句中使用变量字段名或表名一样。您可能必须使用 dynamic SQL,将语句构建为 varchar,然后使用 EXECUTE 执行字符串。
  • 可以在表名或字段名中使用psql变量,如\set table pg_user \\ select * from :"table";

标签: sql database postgresql


【解决方案1】:

一般来说,变量替换确实适用于元命令(以反斜杠开头),但 \copy 是一个例外,如 psql 的 manpage 中所述:

此命令的语法类似于 SQL COPY 命令的语法。 除数据源/目标外的所有选项均按指定 复制。因此,特殊的解析规则适用于 \copy 命令。 特别是 psql 的变量替换规则和 反斜杠转义不适用

我不同意@BaconBits 对 plpgsql 的EXECUTE 可能是答案的问题的评论。与\copy 相反,服务器端语句,无论是动态的还是其他的,都不会访问客户端文件系统。您可以改用COPY,但它需要是超级用户,并且服务器上的postgres 用户可以访问该文件。

我相信从变量文件名到\copy,必须在psql读取之前将变量注入脚本。您可以将 SQL 脚本集成到 shell 脚本中,并将其作为可修补的 here-string 提供给 psql,或者通过 sedperl 或任何类似的 unix-ish 方法对其进行过滤。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 2019-01-28
    • 2013-03-19
    • 2019-01-17
    • 2017-02-25
    相关资源
    最近更新 更多