Ren*_*ger 9 oracle sqlplus scripting
不知何故,似乎 SQL*Plus(至少在 Windows 上)在调用 with@@
以及路径以单点或双点开头时无法定位具有相对路径的脚本。
例如,在x:\some\where
I下有以下目录结构:
script.sql
main-dir\main-sub-dir
call-script.sql
script.sql
Run Code Online (Sandbox Code Playgroud)
即:两个script.sql
但在不同的位置。
script.sql
刚刚下的内容x:\some\where
简直了
prompt SCRIPT root
Run Code Online (Sandbox Code Playgroud)
而另一个script.sql
的内容是
prompt SCRIPT main-dir/main-subdir
Run Code Online (Sandbox Code Playgroud)
call-script.sql
阅读
@@script.sql
@ script.sql
Run Code Online (Sandbox Code Playgroud)
如果我从 SQL*Plus 启动x:\some\where
然后执行
@main-dir/main-sub-dir/call-scripts
Run Code Online (Sandbox Code Playgroud)
输出将是
SCRIPT main-dir/main-subdir
SCRIPT root
Run Code Online (Sandbox Code Playgroud)
这是意料之中的,因为单曲@
应该从 SQL*Plus 的启动位置@@
搜索路径,并且应该从包含脚本的目录中搜索路径。
现在,如果我call-scripts.sql
这样改变:
@@./script.sql
@ ./script.sql
Run Code Online (Sandbox Code Playgroud)
double@@
似乎改变了它的行为,因为它从 SQL*Plus 开始的位置搜索路径,现在输出将是
SCRIPT root
SCRIPT root
Run Code Online (Sandbox Code Playgroud)
这不是我所期望的。
这种行为是否记录在某处,更重要的是,我必须如何更改call-scripts.sql
才能@@../../other-dir/other-sub-dir/script
正确调用相对路径 ( )?
小智 7
是的,这是 Bug 2391334,它已经存在很长时间了,可能在不久的将来不会修复。
解决此问题的一种方法是“知道”脚本的路径,而无需对该路径进行实际硬编码。要在 SQLPlus 中执行此操作需要一个技巧——如果您尝试运行一个不存在的文件,那么您将收到一条包含路径名的错误消息。
所以这是一个实际的演示。为了模仿你的场景,我有:
c:\temp\demo
script.sql
maindir
subdir
call_script.sql
script.sql
Run Code Online (Sandbox Code Playgroud)
我们可以做的是在 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
Run Code Online (Sandbox Code Playgroud)
这里发生的事情是我们正在运行一个不存在的脚本,它返回:
“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
Run Code Online (Sandbox Code Playgroud)
当我们运行它时,我们得到以下信息
SQL> @maindir\mainsubdir\call_script
path was maindir\mainsubdir
script in subdir
script in subdir
Run Code Online (Sandbox Code Playgroud)
你去吧:-)