Đường dẫn SQL * Plus, @ và tương đối


9

Bằng cách nào đó, dường như SQL * Plus (ít nhất là trên Windows) không thể định vị tập lệnh có đường dẫn tương đối khi được gọi bằng @@và khi đường dẫn bắt đầu bằng một dấu chấm đơn hoặc kép.

Ví dụ, dưới x:\some\wheretôi có cấu trúc thư mục sau:

script.sql
main-dir\main-sub-dir
              call-script.sql
              script.sql

Đó là: hai script.sqlnhưng tại các địa điểm khác nhau.

Nội dung của script.sqlchỉ x:\some\wheređơn giản là

prompt SCRIPT root

trong khi script.sqlnội dung của người kia là

prompt SCRIPT main-dir/main-subdir

call-script.sql đọc

@@script.sql
@ script.sql

sản lượng dự kiến

Nếu tôi khởi động SQL * Plus x:\some\wherevà sau đó thực hiện

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

Đầu ra sẽ là

SCRIPT main-dir/main-subdir
SCRIPT root 

Điều này được mong đợi, vì đơn @được cho là tìm kiếm các đường dẫn từ nơi SQL * Plus được bắt đầu và @@được cho là tìm kiếm các đường dẫn từ thư mục chứa tập lệnh.

đầu ra bất ngờ

Bây giờ , nếu tôi thay đổi call-scripts.sqlnhư vậy:

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

nhân đôi @@dường như thay đổi hành vi của nó, trong đó nó tìm kiếm các đường dẫn từ nơi SQL * Plus được bắt đầu và bây giờ đầu ra sẽ là

SCRIPT root
SCRIPT root

đó không phải là điều tôi mong đợi


Hành vi này có được ghi lại ở đâu đó không, và quan trọng hơn, làm thế nào để tôi phải thay đổi call-scripts.sqlđể nó gọi các đường dẫn tương đối ( @@../../other-dir/other-sub-dir/script) chính xác?


Biến môi trường SQLPATH của bạn được đặt thành gì? Điều đó ảnh hưởng đến những thư mục được tìm kiếm.
Philᵀᴹ


Hành vi tương tự trong Linux, FWIW. (Và một dấu và là, chứ không phải @; dường như không có tên thật ). Có vẻ là lỗi, vì nó không nhất quán. Điều duy nhất nảy sinh là đặt một biến nó thành tập lệnh cấp cao nhất với đường dẫn đầy đủ và thực hiện mọi thứ dựa trên đó, nhưng điều đó không thuận tiện trừ khi cấu trúc thư mục bên dưới được cố định.
Alex Poole

Cảm ơn bạn đã chỉ ra điều @ vs ampersands ... Tôi nên biết điều đó, nhưng khi tôi viết bài đăng tôi đã không thực sự chú ý. Bây giờ nó đã được cố định trong tiêu đề.
René Nyffalanger

2
Tôi vừa tấn công sqlplus với strace. Đây là các cuộc gọi có liên quan: pastebin.com/cVK1QQu4 Lưu ý rằng nó không cố gắng thống kê hoặc truy cập các tệp "script.sql" trong bất kỳ thư mục nào khác trước khi thử mở các thư mục được thấy trong đầu ra pastebin.
Philᵀᴹ

Câu trả lời:


7

Phải, đây là Bug 2391334 đã xuất hiện từ lâu và có lẽ sẽ không được sửa trong tương lai gần.

Một cách để làm việc này là "biết" đường dẫn cho các tập lệnh mà không thực sự mã hóa đường dẫn đó. Để thực hiện điều này trong SQLPlus cần một mẹo - nếu bạn cố chạy một tệp không tồn tại, thì bạn sẽ nhận được thông báo lỗi bao gồm tên đường dẫn.

Vì vậy, đây là một bản demo của điều đó trong hành động. Để bắt chước kịch bản của bạn, tôi đã có:

c:\temp\demo
   script.sql
   maindir
      subdir
         call_script.sql
         script.sql

Những gì chúng ta có thể làm là thêm một số lệnh vào phía trước của call_script.sql sẽ chọn đường dẫn. Nó trông hơi kỳ lạ, nhưng bạn không cần phải thay đổi nó - nó chỉ là một thứ cố định mà bạn dán vào

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

Điều đang xảy ra ở đây, là chúng ta đang chạy một kịch bản không tồn tại, trả về:

"SP2-0310: không thể mở tệp" đường dẫn \ _nonexistent_script.sql "

vì vậy với một chút regrec chúng ta có thể trích xuất đường dẫn, lưu trữ nó trong một biến SQLPlus và sau đó sử dụng từ thời điểm đó.

Vì vậy, phiên bản cuối cùng của call_script.sql của bạn sẽ trông như thế này

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

và khi chúng tôi chạy nó, chúng tôi nhận được sau đây

SQL> @maindir\mainsubdir\call_script
path was maindir\mainsubdir
script in subdir
script in subdir

Và ở đó bạn đi :-)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.