Führen Sie ein Skript mit SQLPlus aus, das Leerzeichen, Semikolons und Schrägstriche enthält

15

Gelegentlich erhalte ich ein Skript, das in SQL Developer oder Toad problemlos ausgeführt werden kann, das jedoch geändert werden muss, damit es erfolgreich in SQL * Plus ausgeführt werden kann. Hier ist ein Worst-Case-Beispiel mit mehreren Anweisungen, die jeweils Leerzeilen, Semikolons und Schrägstriche enthalten:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Aus verschiedenen Gründen müssen diese Anweisungen in SQL * Plus ausgeführt werden. Die Leerzeilen lassen sich mit einem einfachen ...

set sqlblanklines on

Mir ist bewusst, dass das sqlterminatorgeändert und / oder deaktiviert werden kann, aber beide Änderungen am Code erfordern würden. Ersteres verschiebt das Problem, ohne es zu beheben, und behebt auch nicht das Problem mit dem eingebetteten Schrägstrich.

Die beste Antwort wäre eine Möglichkeit, die Ausführung dieser Anweisungen ohne Änderung zuzulassen, indem die Umgebung auf irgendeine Weise geändert wird (wie dies bei sqlblanklines der Fall ist). Wenn dies nicht möglich ist, können Sie die Skripte möglicherweise programmgesteuert ändern. Ich versuche manuelle Änderungen zu vermeiden.

Leigh Riffel
quelle
Dieses Problem kann leicht auftreten, wenn die Befehlszeilenausführung von SQLPLUS verwendet wird. Während Sie sich im SQLPLUS-Programm befinden, ist auch der Befehlszeileneditor weiterhin aktiv. Infolgedessen werden Elemente, die für den Befehlszeileneditor relevant sind (Leerzeichen werden als Befehl / Variable interpretiert, Semikolons werden als Befehlsende angesehen). Das ist der Grund, warum ein '@' in einem Passwort nur Herzschmerz verursacht, wenn Sie versuchen, sich anzumelden (alles rechts von @ wird als Name einer Datenbank angesehen). Während einer größeren Bereitstellung haben wir Probleme mit Leerzeichen festgestellt, die uns gezwungen haben, Inhalte über TOAD bereitzustellen. SQLPLUS war nutzlos für
TomV
Danke für deine Gedanken. Um zu klären, ist Ihre Antwort, dass das, was ich verlange, unmöglich ist?
Leigh Riffel,
Können Sie die Zeilenumbrüche innerhalb der Zeichenfolge in chr (10) konvertieren? S wird die Einfügung in einer Zeile aufgeführt?
Chris Saxon
@ChrisSaxon Ich kann, aber dieses Problem ist, wie Rückgaben, die codiert werden sollen, und Rückgaben, die als Teil der Syntax in Ruhe gelassen werden müssen, zu unterscheiden sind. Wenn Sie eine Möglichkeit haben, dies zu tun, posten Sie dies bitte als Antwort.
Leigh Riffel

Antworten:

8

Das meiste können Sie mit login.sql erledigen. login.sql wird während der - überraschenden - Anmeldung ausgeführt und aus Ihrem SQLPATH oder dem aktuellen Verzeichnis geladen. Für die Beispiele, die Sie gegeben haben, haben Sie wirklich den schlechtesten Fall gewählt.

Problem ist der sqlterminator. Was auch immer Sie dort einfügen, der Schrägstrich wird als kostenloser SQL-Minimator beibehalten. Darüber hinaus sucht sqlplus zuerst nach dem sqlterminator und führt dies durch, bevor zum Zeichenfolgenabschluss gescannt wird. Ein Fehler, wenn Sie mich fragen. Der Schrägstrich kann in einer Zeichenfolge verwendet werden, solange er nicht in einer separaten Zeile steht. Sobald sqlplus das als sqlterminator angegebene Zeichen findet, ignoriert es alles andere und hört auf zu lesen.

Der Schrägstrich kann behandelt werden, solange er nicht alleine in einer Zeile steht.

login.sql enthält:

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 enthält:

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

Führen Sie das Skript aus:

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.

Keine Notwendigkeit, mit Anfangs- / Endblöcken zu fummeln. Kann sqlterminator im Befehl nicht verarbeiten, egal wo es sich in einer Zeichenfolge befindet oder nicht, kann keine Zeilen mit Schrägstrich allein in einer Zeile in einer Zeichenfolge verarbeiten.

ik_zelf
quelle
1
Danke für den Beweis. In ähnlicher Weise verwende ich bereits eine login.sql-Datei. Das bestätigt also im Grunde, dass ich das, was ich tun möchte, nicht tun kann.
Leigh Riffel
1
Eine kleine Variation ist die Verwendung eines Runner-Skripts, das die Einstellungen vornimmt und das eigentliche Skript aufruft. Würde sqlplus leigh / leigh @ orcl @runner leigh werden. Das ist etwas flexibler als login.sql
ik_zelf 10.08.12
1

Das Einfügen von Anweisungen mit Leerzeilen und Semikolons ist erfolgreich, wenn sie in BEGIN ... END-Blöcken platziert werden. Diese Änderung könnte mit einem Skript durchgeführt werden, aber das Skript würde fehlschlagen, wenn es DDL-Anweisungen enthält, die nicht in einem Block ausgeführt werden können, ohne sofort ausgeführt zu werden.

Diese Lösung behebt auch nicht das eingebettete Problem.

Leigh Riffel
quelle
In der Vergangenheit habe ich dazu ein Perl / DBD-Skript verwendet, um sqlplus zu vermeiden.
Gerne
@Phil Vielen Dank, aber SQLPlus funktioniert in 99,9% der Situationen einwandfrei. Daher möchte ich der Mischung lieber kein weiteres Tool hinzufügen.
Leigh Riffel
1

Mein Workaround:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Es scheint, als würde das Befehlsende in der body-Anweisung ignoriert.

Bocian
quelle
Sehen Sie meine Antwort, warum dies keine gute Lösung für DDL-Anweisungen oder eingebettete Schrägstriche ist.
Leigh Riffel
-1
set sqlterminator OFF
<...>
set sqlterminator ON
user28627
quelle
1
Und wie hilft das?
24.