Oracle

SQL*Plus、@ 和相對路徑

  • March 25, 2017

不知何故,似乎 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*Plusx:\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)?

是的,這是已經存在很長時間的錯誤 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

你去吧:-)

引用自:https://dba.stackexchange.com/questions/17347