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а потім роблю a

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

Вихід буде

SCRIPT main-dir/main-subdir
SCRIPT root 

Це очікується, оскільки сингл @повинен шукати шляхи, з яких був запущений SQL * Plus, і @@повинен шукати шляхи з каталогу, що містить скрипт.

несподіваний вихід

Тепер , якщо я зміню call-scripts.sqlтак:

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

подвійний, @@схоже, змінює свою поведінку, оскільки він шукає шляхи з того місця, з якого був запущений SQL * Plus, і вихід тепер буде

SCRIPT root
SCRIPT root

що не те, чого я очікував.


Чи де-не-де задокументована така поведінка, і що ще важливіше, як я повинен змінитись, call-scripts.sqlщоб вона @@../../other-dir/other-sub-dir/scriptправильно називала відносні шляхи ?


Для чого встановлена ​​ваша змінна середовище SQLPATH? Це впливає на пошук каталогів.
Philᵀᴹ


Така ж поведінка під Linux, FWIW. (І амперсанд - це &, не @; що , схоже, не має справжнього імені ). Здається, це помилка, оскільки це непослідовно. Єдине, що спадає на думку - це встановити змінну їй сценарію верхнього рівня з повним шляхом і зробити все на основі цього, але це не дуже зручно, якщо не буде виправлена ​​структура каталогів нижче.
Алекс Пул

Дякую за вказівку на річ @ vs ampersands ... Я повинен був це знати, але коли я написав повідомлення, я не звернув уваги. Тепер це зафіксовано в заголовку.
Рене Ніффенеггер

2
Я просто напав на sqlplus з strace. Ось відповідні дзвінки: pastebin.com/cVK1QQu4 Зауважте, що він не намагався стати чи отримати доступ до файлів "script.sql" в будь-яких інших каталогах, перш ніж намагатися відкрити ті, які бачать у виведенні пастіна.
Philᵀᴹ

Відповіді:


7

Так, це помилка 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: не вдається відкрити файл" шлях \ _noexistent_script.sql "

тож за допомогою невеликого regexp ми можемо витягти шлях, зберегти його у змінній 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

а ти їдеш :-)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.