Eseguire uno script con SQLPlus contenente spazi vuoti, punti e virgola e barre


15

Occasionalmente riceverò uno script che funzionerà bene in SQL Developer o Toad, ma richiede modifiche per essere eseguito correttamente da SQL * Plus. Ecco un esempio nel caso peggiore contenente più istruzioni ognuna con righe vuote, punti e virgola e barre:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Per vari motivi, queste istruzioni devono essere eseguite da SQL * Plus. Le righe vuote sono facili da risolvere con un semplice ...

set sqlblanklines on

Sono consapevole che sqlterminatorpuò essere modificato e / o disattivato, ma entrambi richiederebbero modifiche al codice, il primo sposta il problema senza risolverlo e non risolve il problema della barra incorporata.

La risposta migliore sarebbe un modo per consentire a queste istruzioni di funzionare senza modifiche cambiando l'ambiente in qualche modo (come fa sqlblanklines). Se ciò non è possibile, allora forse c'è un modo per modificare programmaticamente gli script. Sto cercando di evitare modifiche manuali.


Questo problema può verificarsi facilmente quando si utilizza l'esecuzione da riga di comando di SQLPLUS. Mentre ci si trova all'interno del programma SQLPLUS, anche l'editor della riga di comando è ancora attivo. Di conseguenza, gli elementi rilevanti per l'editor della riga di comando (gli spazi vuoti vengono interpretati come comando / variabile, i punti e virgola vengono visualizzati come fine del comando). Ecco perché avere un '@' in una password non provoca altro che angoscia quando si tenta di accedere (tutto a destra di @ è visto come il nome di un DB). Durante un'implementazione importante, abbiamo riscontrato problemi con spazi vuoti che ci hanno costretto a distribuire elementi tramite TOAD. SQLPLUS era inutile
TomV il

Grazie per i tuoi pensieri Quindi, per chiarire è la tua risposta che ciò che sto richiedendo è impossibile?
Leigh Riffel,

Puoi convertire i ritorni a capo all'interno della stringa in chr (10) s insert è elencato su una riga?
Chris Saxon,

@ChrisSaxon Posso, ma questo problema è come distinguere i ritorni che dovrebbero essere codificati e quelli che devono essere lasciati soli come parte della sintassi. Se hai un modo per farlo, pubblica questo come risposta.
Leigh Riffel,

Risposte:


8

Puoi fare la maggior parte di questo usando un login.sql. login.sql viene eseguito durante - sorprendente - login e viene caricato da SQLPATH o dalla directory corrente. Per gli esempi che hai dato, hai davvero scelto il caso peggiore.

Il problema è il sqlterminator. Qualunque cosa tu inserisca, la barra viene mantenuta come un sqlterminator gratuito. Accanto a ciò, sqlplus esegue innanzitutto la ricerca del sqlterminator e lo fa prima di eseguire la scansione sul terminatore di stringa. Un bug se me lo chiedi. La barra in avanti può essere utilizzata in una stringa purché non sia sola su una linea separata. Non appena sqlplus trova il carattere specificato come sqlterminator, ignora tutto il resto e interrompe la lettura.

La barra in avanti può essere gestita, purché non sia sola su una linea.

login.sql contiene:

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

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

eseguire lo script:

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.

Non è necessario giocherellare con i blocchi di inizio / fine. Impossibile gestire sqlterminator all'interno del comando, indipendentemente da dove si trovi, in una stringa o no, non è in grado di gestire le linee con barra in avanti da solo su una linea in una stringa.


1
Grazie per la prova Sto già usando una configurazione del file login.sql in modo simile. Quindi, in sostanza, questo conferma che il motivo per cui vorrei fare non può essere fatto.
Leigh Riffel,

1
una piccola variazione consiste nell'utilizzare uno script runner che esegue le impostazioni e chiama lo script reale. Diventerebbe sqlplus leigh / leigh @ orcl @runner leigh. È un po 'più flessibile di login.sql
ik_zelf il

1

Le istruzioni di inserimento con righe vuote e punti e virgola avranno esito positivo se inserite all'interno dei blocchi BEGIN ... END. Questa modifica potrebbe essere eseguita utilizzando uno script, ma lo script non verrebbe eseguito se contenesse istruzioni DDL che non possono essere eseguite all'interno di un blocco senza eseguire immediate.

Questa soluzione inoltre non risolve il problema / incorporato.


In passato ho usato uno script perl / DBD per fare questo per evitare sqlplus. Felice di condividere ...
Philᵀᴹ

@Phil Grazie, ma SQLPlus funziona bene nel 99,9% delle situazioni, quindi preferirei non aggiungere un altro strumento al mix.
Leigh Riffel,

1

La mia soluzione alternativa:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Sembra che il terminatore dei comandi sia ignorato all'interno dell'istruzione body.


Vedi la mia risposta sul perché questa non è una buona soluzione per le dichiarazioni DDL o le barre incorporate.
Leigh Riffel,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.