web-dev-qa-db-ja.com

SQL * Plus、@、および相対パス

どういうわけか、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をどのように変更する必要がありますか?

9

うん、これは長い間存在していたバグ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

そしてそこに行く:-)

7
Connor McDonald