どういうわけか、SQL * Plus(少なくともWindowsでは)が@@
で呼び出され、パスがシングルまたはダブルドットで始まる場合、相対パスを持つスクリプトを見つけることができないようです。
たとえば、x:\some\where
の下には、次のディレクトリ構造があります。
script.sql
main-dir\main-sub-dir
call-script.sql
script.sql
つまり、2つの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
x:\some\where
からSQL * Plusを起動してから、
@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
これはnotです。
この動作はどこかに文書化されていますか?そしてもっと重要なことですが、相対パス(call-scripts.sql
)を正しく呼び出すために@@../../other-dir/other-sub-dir/script
をどのように変更する必要がありますか?
うん、これは長い間存在していたバグ2391334であり、おそらく近い将来には修正されないでしょう。
これを回避する1つの方法は、スクリプトのパスを「知る」ことですなし実際にそのパスをハードコーディングします。 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
そしてそこに行く:-)