我正在尝试创建一组脚本来修改 Postgres 9.6 数据库中的某些表。这些脚本存储在各种目录中,并依次从一个主协调器脚本调用。我正在 psql 中运行脚本。
在主脚本中,我用来\ir指定其他脚本的相对路径名。因此,我可以从任何地方运行 psql,并且主脚本将找到其他脚本。这按预期工作。
然而,在某些脚本中,我使用\copy命令从 CSV 文件加载数据。不幸的是,似乎输入文件名\copy始终被解释为相对于 psql 的当前工作目录,而不是相对于其脚本的目录,即使我\copy使用\ir.
例如,假设我从 开始psql,C:\并计划使用以下文件:
C:\
dir1\
script1.sql
dir2\
script2.sql
input.csv
Run Code Online (Sandbox Code Playgroud)
我可以使用调用第一个脚本\ir dir1/script1.sql。效果很好。
此外,该脚本可以使用 调用第二个脚本\ir dir2/script2.sql。这也很好用。
问题是\copy第二个脚本中的命令:
\COPY foo.bar (col1) FROM 'input.csv' WITH (FORMAT CSV);
Run Code Online (Sandbox Code Playgroud)
input.csv除非存在于会话的当前目录中,否则此操作将失败psql。因此,我的问题是:
\COPY ... FROM从脚本内部调用命令,而不要求用户psql从相对于输入文件的特定目录运行会话?我知道我可以使用绝对路径名,但在升级不同的部署时,我们将从各种不同的计算机/平台运行此脚本,因此在这种情况下没有可用的通用绝对路径。我正在寻找某种相对或可配置的路径解决方案。
先感谢您。
我认为没有办法表明\copy该文件相对于脚本的位置,但您可以使用\cd之前更改当前目录\copy。
\cd插入变量,以便可以使用以下命令在命令行上传递目录-v:
psql -vscriptdir="c:\path\to\script" -f c:\path\to\script\script1.sql
Run Code Online (Sandbox Code Playgroud)
在包含任何内容之前,假设顶层脚本中有此命令:
\cd :scriptdir
Run Code Online (Sandbox Code Playgroud)
(除非-f参数只是一个没有路径的文件:在这种情况下没有必要,因为当前目录已经设置在脚本所在的位置)
那么子目录中每次包含脚本都应该是:
\cd dir2
\i script2.sql
\cd ..
Run Code Online (Sandbox Code Playgroud)
(相对于\ir dir2/script2.sql)
当script2.sql调用\copy与之相关的文件时,将找到该数据文件,因为它位于当前目录中。
这应该递归地工作,假设子目录中的脚本也遵循该约定,并且它们不会执行不相关的操作\cd,从而干扰\cd ..返回顶部的等待发生。