SQL * Plus,@和相对路径


9

某种程度上,似乎似乎SQL * Plus(至少在Windows上)在用调用@@以及路径以单点或双点开头时无法找到具有相对路径的脚本。

例如,在x:\some\where下面,我具有以下目录结构:

script.sql
main-dir\main-sub-dir
              call-script.sql
              script.sql

也就是说:两个,script.sql但位置不同。

script.sql正下方的内容x:\some\where很简单

prompt SCRIPT root

而对方script.sql的内容是

prompt SCRIPT main-dir/main-subdir

call-script.sql

@@script.sql
@ script.sql

预期产量

如果我从中启动SQL * Plus x:\some\where,然后执行

@main-dir/main-sub-dir/call-scripts

输出将是

SCRIPT main-dir/main-subdir
SCRIPT root 

这是预料之中的,因为该单曲@应该从SQL * Plus的起始位置@@搜索路径,并且应该从包含脚本的目录中搜索路径。

意外的输出

现在,如果我更改为call-scripts.sql

@@./script.sql
@ ./script.sql

double @@似乎改变了它的行为,因为它从SQL * Plus的起始位置搜索路径,现在输出为

SCRIPT root
SCRIPT root

不是我所期望的。


此行为是否已记录在某处,更重要的是,我必须如何进行更改call-scripts.sql以使其@@../../other-dir/other-sub-dir/script正确调用相对路径()?


您的SQLPATH环境变量设置为什么?这会影响要搜索的目录。
菲尔(Philᵀᴹ)2012年


在Linux和FWIW下的行为相同。(“&”号是&,而不是@; 似乎没有真名)。似乎是错误,因为不一致。唯一想到的就是在顶级脚本中为变量设置完整路径,并根据此路径执行所有操作,但这并不是很方便,除非修复了下面的目录结构。
亚历克斯·普尔

感谢您指出@ vs&符之类的东西...我早该知道的,但是当我写这篇文章时,我并没有真正注意。现在,它已在标题中固定。
勒内Nyffenegger

2
我只是用攻击了sqlplus strace。这里是相关的调用:pastebin.com/cVK1QQu4注意,在尝试打开pastebin输出中看到的文件之前,它没有尝试统计或访问任何其他目录中的“ script.sql”文件。
菲尔(Philᵀᴹ)2012年

Answers:


7

是的,这是已经存在很长时间的Bug 2391334,并且可能不会在不久的将来修复。

解决此问题的一种方法是“知道”脚本的路径,而无需实际对该路径进行硬编码。在SQLPlus中执行此操作需要技巧-如果尝试运行不存在的文件,则会收到一条包含路径名的错误消息。

因此,这是一个实际的演示。为了模拟您的情况,我得到了:

c:\temp\demo
   script.sql
   maindir
      subdir
         call_script.sql
         script.sql

我们可以做的是在call_script.sql的前面添加一些命令,以选择路径。它看起来有些奇怪,但是您无需更改它-它只是粘贴的固定内容

set termout off
spool _path_finder.sql
@@_nonexistent_script.sql
spool off;

var path varchar2(100);
set serverout on
declare
  output varchar2(1000) := regexp_replace(replace(q'{
@_path_finder.sql
}',chr(10)),'.*"(.*)".*','\1');
begin 
  :path:=substr(output,1,length(output)-24);
end;
/
col path new_val path
select :path path from dual;
set termout on

这里发生的是我们正在运行一个不存在的脚本,该脚本返回:

“ SP2-0310:无法打开文件“ path \ _nonexistent_script.sql”

因此,使用一点正则表达式,我们可以提取路径,将其存储在SQLPlus变量中,然后从此开始使用。

因此,您的call_script.sql的最终版本如下所示

set termout off
spool _path_finder.sql
@@_nonexistent_script.sql
spool off;

var path varchar2(100);
set serverout on
declare
  output varchar2(1000) := regexp_replace(replace(q'{
@_path_finder.sql
}',chr(10)),'.*"(.*)".*','\1');
begin 
  :path:=substr(output,1,length(output)-24);
end;
/
col path new_val path
select :path path from dual;
set termout on
prompt path was &path      

@@&path\script.sql
@&path\script.sql

当我们运行它时,我们得到以下内容

SQL> @maindir\mainsubdir\call_script
path was maindir\mainsubdir
script in subdir
script in subdir

然后你去:-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.