我正在尝试创建一个脚本集合来修改 Postgres 9.6 数据库中的一些表。这些脚本存储在各种目录中,并依次从一个主协调器脚本中调用。我在 psql 中运行脚本。
在主脚本中,我\ir
用来指定其他脚本的相对路径名。因此,我可以从任何地方运行 psql,主脚本会找到其他脚本。这按预期工作。
但是,在某些脚本中,我使用该\copy
命令从 CSV 文件加载数据。不幸的是,\copy
即使我使用.\copy
\ir
例如,假设我从 开始psql
,C:\
并计划使用以下文件:
C:\
dir1\
script1.sql
dir2\
script2.sql
input.csv
我可以使用调用第一个脚本\ir dir1/script1.sql
。这很好用。
此外,该脚本可以使用\ir dir2/script2.sql
. 这也很好。
问题是\copy
第二个脚本中的命令:
\COPY foo.bar (col1) FROM 'input.csv' WITH (FORMAT CSV);
除非会话input.csv
的当前目录中存在,否则这将失败。psql
因此,我的问题是:
- 有什么方法可以让我
\COPY ... FROM
从脚本内部调用命令,而无需用户psql
从相对于输入文件的特定目录运行会话?
我知道我可以使用绝对路径名,但是在升级我们不同的部署时,我们将在各种不同的机器/平台上运行这个脚本,所以在这种情况下没有通用的绝对路径可以工作。我正在寻找某种相对或可配置的路径解决方案。
先感谢您。
我认为没有办法表明
\copy
该文件是相对于脚本的位置,但您可以使用\cd
之前更改当前目录\copy
。\cd
插入变量,以便目录可以在命令行上传递-v
:在包含任何内容之前,假设顶层脚本中有这个命令:
(除非
-f
参数只是一个没有路径的文件:在这种情况下,没有必要,因为当前目录已经设置在脚本所在的位置)那么子目录中包含的每个脚本都应该是:
(相对于
\ir dir2/script2.sql
)何时使用与其相关的文件进行
script2.sql
调用\copy
,将找到数据文件,因为它位于当前目录中。这应该递归地工作,假设子目录中的脚本也遵循该约定,并且它们不会执行不相关的操作
\cd
,这会干扰在\cd ..
返回顶部的路上等待发生。如果你想存储数据/(root)从本地机器获取数据并与另一台远程机器上的 PostgreSQL 服务器通信,你不能简单地使用
COPY
.\copy
尝试psql 中的元命令。它是 SQL 命令的包装器COPY
并使用本地文件。您的文件名应该在 Windows 机器上按原样工作,但 PostgreSQL 将其解释为服务器上的本地文件名,这可能是 Unix 派生的,文件名必须以“/”开头。
如果以下情况属实,
psql
从C:\
C:\dir1\dir2\input.csv
是文件。然后你应该可以像这样加载它,
我遇到过这个完全相同的用例,我并不喜欢
\cd
针对我的特定情况的解决方案。我制定的解决方案相当简单,但只有在 CSV 文件的唯一目的是提供表格时才有意义。在我的设置中,CSV 文件与使用它们的 SQL 文件一起存储在版本控制中,因此更改很容易。
代替:
我用了:
换句话说,只需将 CSV 数据直接移动到 SQL 文件中。
绝对不适合所有用例,但我认为应该在这里提到它作为替代解决方案。:)
如需进一步阅读,请参阅该
\copy
功能的官方文档。