Uruchom skrypt z SQLPlus zawierającym spacje, średniki i ukośniki

15

Czasami dostaję skrypt, który będzie działał poprawnie w SQL Developer lub Toad, ale wymaga modyfikacji, aby pomyślnie uruchomić z SQL * Plus. Oto najgorszy przykład zawierający wiele instrukcji z pustymi wierszami, średnikami i ukośnikami:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Z różnych powodów instrukcje te muszą być uruchamiane z SQL * Plus. Puste linie można łatwo rozwiązać za pomocą prostego ...

set sqlblanklines on

Wiem, że sqlterminatormożna to zmienić i / lub wyłączyć, ale oba wymagają modyfikacji kodu, ten pierwszy przenosi problem bez jego rozwiązania i nie rozwiązuje problemu osadzonego ukośnika.

Najlepszą odpowiedzią byłby sposób na uruchomienie tych instrukcji bez modyfikacji poprzez zmianę środowiska w jakiś sposób (tak jak robi to sqlblanklines). Jeśli nie jest to możliwe, być może istnieje sposób na programową modyfikację skryptów. Staram się unikać ręcznych zmian.

Leigh Riffel
źródło
Ten problem może się łatwo zdarzyć podczas korzystania z SQLPLUS wykonywania wiersza polecenia. Podczas pracy w programie SQLPLUS edytor wiersza poleceń jest również nadal aktywny. W rezultacie elementy istotne dla edytora wiersza poleceń (puste spacje są interpretowane jako polecenie / zmienna, średniki są traktowane jako koniec polecenia). Dlatego posiadanie znaku „@” w haśle powoduje jedynie ból serca podczas próby zalogowania się (wszystko po prawej stronie @ jest postrzegane jako nazwa bazy danych). Podczas dużego wdrożenia znaleźliśmy problemy z pustymi miejscami, które zmusiły nas do wdrożenia rzeczy za pośrednictwem TOAD. SQLPLUS był bezużyteczny dla
TomV
Dziękuję za twoje przemyślenia. Tak więc, aby wyjaśnić, czy twoja odpowiedź jest niemożliwa?
Leigh Riffel
Czy potrafisz przekonwertować znaki powrotu karetki w ciągu na wstawkę chr (10) wymienioną w jednym wierszu?
Chris Saxon
@ChrisSaxon Mogę, ale ten problem polega na tym, jak rozróżnić zwroty, które powinny być zakodowane, i zwroty, które należy pozostawić w spokoju jako część składni. Jeśli masz na to sposób, prześlij to jako odpowiedź.
Leigh Riffel,

Odpowiedzi:

8

Możesz to zrobić w większości za pomocą login.sql. login.sql jest wykonywany podczas - zaskakującego - logowania i jest ładowany z SQLPATH lub bieżącego katalogu. Dla podanych przykładów naprawdę wybrałeś najgorszy przypadek.

Problemem jest sqlterminator. Cokolwiek tam umieścisz, ukośnik jest zachowywany jako darmowy sqlterminator. Oprócz tego sqlplus najpierw skanuje w poszukiwaniu sqlterminatora i robi to przed skanowaniem do terminatora ciągów. Błąd, jeśli mnie zapytasz. Ukośnika do przodu można używać w ciągu, o ile nie jest on sam na osobnej linii. Gdy tylko sqlplus znajdzie znak określony jako sqlterminator, ignoruje wszystko inne i przestaje czytać.

Ukośnik do przodu może być obsługiwany, o ile nie jest sam na linii.

login.sql zawiera:

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 zawiera:

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/
';

uruchom skrypt:

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.

Nie musisz majstrować przy blokach początkowych / końcowych. Nie może obsłużyć polecenia sqlterminator wewnątrz polecenia, bez względu na to, gdzie się znajduje, w ciągu znaków, czy nie, nie może obsłużyć wierszy z samym ukośnikiem w linii w ciągu.

ik_zelf
źródło
1
Dziękuję za dowód. Już używam podobnie konfiguracji pliku login.sql. To w zasadzie potwierdza, że ​​nie mogę tego zrobić.
Leigh Riffel,
1
niewielką odmianą jest użycie skryptu uruchamiającego, który dokonuje ustawień i wywołuje prawdziwy skrypt. Byłby sqlplus leigh / leigh @ orcl @runner leigh. To jest trochę bardziej elastyczne niż login.sql
ik_zelf
1

Wstawianie instrukcji z pustymi wierszami i średnikami zakończy się powodzeniem, jeśli zostaną umieszczone w blokach BEGIN ... END. Tej zmiany można dokonać za pomocą skryptu, ale skrypt nie powiedzie się, jeśli zawiera instrukcje DDL, których nie można uruchomić w bloku bez natychmiastowego wykonania.

To rozwiązanie również nie rozwiązuje problemu osadzonego / problemu.

Leigh Riffel
źródło
W przeszłości korzystałem ze skryptu perl / DBD, aby tego uniknąć, aby uniknąć sqlplus. Z przyjemnością dzielę się ...
Philᵀᴹ
@Phil Dziękuję, ale SQLPlus działa dobrze w 99,9% sytuacji, więc wolałbym nie dodawać innego narzędzia do miksu.
Leigh Riffel,
1

Moje obejście:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Wygląda na to, że terminator poleceń jest ignorowany w instrukcji body.

Bocian
źródło
Zobacz moją odpowiedź, dlaczego nie jest to dobre rozwiązanie dla instrukcji DDL lub osadzonych ukośników.
Leigh Riffel
-1
set sqlterminator OFF
<...>
set sqlterminator ON
użytkownik 28627
źródło
1
Jak to pomoże?
dezso