Jalankan skrip dengan SQLPlus yang berisi blank, semi-titik dua, dan garis miring

15

Kadang-kadang saya akan mendapatkan skrip yang akan berjalan baik di SQL Developer atau Toad, tetapi membutuhkan modifikasi agar dapat dijalankan dengan sukses dari SQL * Plus. Berikut ini adalah contoh kasus terburuk yang berisi beberapa pernyataan, masing-masing dengan garis kosong, titik koma, dan garis miring:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Untuk berbagai alasan pernyataan ini perlu dijalankan dari SQL * Plus. Garis kosong mudah untuk diselesaikan dengan ...

set sqlblanklines on

Saya menyadari bahwa sqlterminatordapat diubah dan / atau dimatikan, tetapi keduanya akan memerlukan modifikasi pada kode, yang pertama memindahkan masalah tanpa menyelesaikannya dan tidak menyelesaikan masalah slash yang tertanam.

Jawaban terbaik adalah cara untuk memungkinkan pernyataan ini berjalan tanpa modifikasi dengan mengubah lingkungan dalam beberapa cara (seperti yang dilakukan sqlblanklines). Jika itu tidak mungkin, maka mungkin ada cara untuk memodifikasi skrip secara terprogram. Saya mencoba menghindari perubahan manual.

Leigh Riffel
sumber
Masalah ini dapat dengan mudah terjadi ketika menggunakan eksekusi baris perintah dari SQLPLUS. Saat Anda berada di dalam program SQLPLUS, editor baris perintah juga masih aktif. Akibatnya, item yang relevan dengan editor baris perintah (spasi kosong ditafsirkan sebagai perintah / variabel, semi-titik dua dilihat sebagai akhir perintah). Itulah sebabnya memiliki '@' dalam kata sandi tidak menyebabkan apa-apa selain sakit hati ketika Anda mencoba masuk (semua yang ada di sebelah kanan @ dilihat sebagai nama DB). Selama penyebaran besar, kami menemukan masalah dengan ruang kosong yang memaksa kami untuk menyebarkan barang melalui TOAD. SQLPLUS tidak berguna untuk
TomV
Terima kasih atas pemikiran anda Jadi, untuk mengklarifikasi adalah jawaban Anda bahwa apa yang saya minta tidak mungkin?
Leigh Riffel
Bisakah Anda mengonversi carriage return dalam string ke chr (10) yang dimasukkan dalam satu baris?
Chris Saxon
@ ChrisSaxon saya bisa, tetapi masalah ini adalah bagaimana membedakan pengembalian yang harus dikodekan dan kembali yang perlu dibiarkan sendiri sebagai bagian dari sintaks. Jika Anda memiliki cara untuk melakukan ini, silakan posting ini sebagai jawaban.
Leigh Riffel

Jawaban:

8

Anda dapat melakukan sebagian besar dari ini dengan menggunakan login.sql. login.sql dijalankan selama - mengejutkan - login dan diambil dari SQLPATH Anda atau direktori saat ini. Untuk contoh yang Anda berikan, Anda benar-benar memilih kasus terburuk.

Masalahnya adalah sqlterminator. Apa pun yang Anda masukkan ke sana, garis miring akan dipertahankan sebagai sqlterminator gratis. Di sebelahnya, sqlplus memindai pertama untuk sqlterminator dan melakukan ini sebelum memindai ke terminator string. Bug jika Anda bertanya kepada saya. Garis miring ke depan dapat digunakan dalam string selama itu tidak sendirian pada garis yang terpisah. Segera setelah sqlplus menemukan karakter yang ditentukan sebagai sqlterminator, ia mengabaikan semua yang lain dan berhenti membaca.

Garis miring ke depan dapat ditangani, asalkan tidak sendirian di garis.

login.sql berisi:

prompt run login.sql
show sqlterminator
show sqlblanklines
set sqlblanklines on
set sqlterminator ';'
show sqlterminator
show sqlblanklines
prompt ready login.sql
set echo on

leigh.sql berisi:

INSERT INTO t1 VALUES ('fail bc semicolon
a;a
/
'); 

INSERT INTO t1 VALUES ('fail bc solo /


aa
/
');

INSERT INTO t1 VALUES ('ok / not solo


aa
/a
');

DELETE FROM t1 WHERE a = 'c


a/
';

jalankan skrip:

sqlplus leigh/leigh@orcl @leigh
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Aug 9 22:36:20 2012

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

run login.sql
sqlterminator ";" (hex 3b)
sqlblanklines OFF
sqlterminator ";" (hex 3b)
sqlblanklines ON
ready login.sql
SQL> INSERT INTO t1 VALUES ('fail bc semicolon
  2  a;a
  3  /
ERROR:
ORA-01756: quoted string not properly terminated


SQL> ');
SP2-0042: unknown command "')" - rest of line ignored.
SQL> 
SQL> INSERT INTO t1 VALUES ('fail bc solo /
  2  
  3  
  4  aa
  5  /
ERROR:
ORA-01756: quoted string not properly terminated


SQL> ');
SP2-0042: unknown command "')" - rest of line ignored.
SQL> 
SQL> INSERT INTO t1 VALUES ('ok / not solo
  2  
  3  
  4  aa
  5  /a
  6  ');

1 row created.

SQL> 
SQL> DELETE FROM t1 WHERE a = 'c
  2  
  3  
  4  a/
  5  ';

0 rows deleted.

Tidak perlu bermain-main dengan blok awal / akhir. Tidak dapat menangani sqlterminator di dalam perintah, di mana pun ia berada, dalam sebuah string atau tidak, tidak dapat menangani garis dengan garis miring sendiri pada garis dalam string.

ik_zelf
sumber
1
Terima kasih atas buktinya. Saya sudah menggunakan pengaturan file login.sql sama. Jadi pada dasarnya ini menegaskan bahwa mengapa saya ingin melakukan tidak dapat dilakukan.
Leigh Riffel
1
sedikit variasi adalah dengan menggunakan skrip pelari yang melakukan pengaturan dan memanggil skrip nyata. Akan menjadi sqlplus leigh / leigh @ orcl @runner leigh. Itu sedikit lebih fleksibel daripada login.sql
ik_zelf
1

Masukkan pernyataan dengan garis kosong dan semi-titik dua akan berhasil jika ditempatkan di dalam BEGIN ... END blok. Perubahan ini bisa dilakukan dengan menggunakan skrip, tetapi skrip akan gagal jika berisi pernyataan DDL yang tidak dapat dijalankan di dalam blok tanpa langsung dieksekusi.

Solusi ini juga tidak menyelesaikan masalah tertanam /.

Leigh Riffel
sumber
Di masa lalu saya telah menggunakan skrip perl / DBD untuk melakukan ini untuk menghindari sqlplus. Senang berbagi ...
Philᵀᴹ
@ Phil Terima kasih, tetapi SQLPlus berfungsi dengan baik dalam 99,9% situasi, jadi saya lebih suka tidak menambahkan alat lain ke dalam campuran.
Leigh Riffel
1

Solusi saya:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Sepertinya terminator perintah diabaikan di dalam pernyataan body.

Bocian
sumber
Lihat jawaban saya mengapa ini bukan solusi yang baik untuk pernyataan DDL atau slash yang disematkan.
Leigh Riffel
-1
set sqlterminator OFF
<...>
set sqlterminator ON
pengguna28627
sumber
1
Dan bagaimana ini akan membantu?
dezso