Ejecute un script con SQLPlus que contenga espacios en blanco, punto y coma y barras inclinadas


15

Ocasionalmente, obtendré un script que funcionará bien en SQL Developer o Toad, pero requiere modificación para que se ejecute con éxito desde SQL * Plus. Aquí hay un ejemplo del peor de los casos que contiene varias declaraciones, cada una con líneas en blanco, punto y coma y barras diagonales:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Por varias razones, estas declaraciones deben ejecutarse desde SQL * Plus. Las líneas en blanco son fáciles de resolver con un simple ...

set sqlblanklines on

Soy consciente de que sqlterminatorse puede cambiar y / o desactivar, pero ambos requerirían modificaciones en el código, el primero mueve el problema sin resolverlo y tampoco resuelve el problema de la barra inclinada incrustada.

La mejor respuesta sería una manera de permitir que estas declaraciones se ejecuten sin modificación cambiando el entorno de alguna manera (como lo hace sqlblanklines). Si eso no es posible, entonces quizás haya una manera de modificar mediante programación los scripts. Estoy tratando de evitar cambios manuales.


Este problema puede suceder fácilmente cuando se usa la ejecución de línea de comandos de SQLPLUS. Mientras está dentro del programa SQLPLUS, el editor de línea de comandos también está activo. Como resultado, los elementos que son relevantes para el editor de línea de comando (los espacios en blanco se interpretan como comando / variable, los punto y coma se ven como el final del comando). Es por eso que tener una '@' en una contraseña no causa más que dolor de corazón cuando intenta iniciar sesión (todo a la derecha de @ se ve como el nombre de una base de datos). Durante una implementación importante, encontramos problemas con los espacios en blanco que nos obligaron a implementar cosas a través de TOAD. SQLPLUS era inútil para
TomV

Gracias por tus pensamientos. Entonces, ¿aclarar es su respuesta que lo que solicito es imposible?
Leigh Riffel

¿Puede convertir los retornos de carro dentro de la cadena a chr (10) s insert aparece en una línea?
Chris Saxon

@ChrisSaxon puedo, pero este problema es cómo distinguir los retornos que deben codificarse y los retornos que deben dejarse solos como parte de la sintaxis. Si tiene una manera de hacerlo, publíquelo como respuesta.
Leigh Riffel

Respuestas:


8

Puede hacer la mayor parte de esto utilizando un login.sql. login.sql se ejecuta durante un inicio de sesión sorprendente y se carga desde su SQLPATH o el directorio actual. Para los ejemplos que dio, realmente eligió el peor de los casos.

El problema es el sqlterminator. Independientemente de lo que ponga allí, la barra diagonal se mantiene como un sqlterminator gratuito. Además de eso, sqlplus primero escanea el sqlterminator y lo hace antes de escanear al terminador de cadena. Un error si me preguntas. La barra diagonal se puede usar en una cadena siempre que no esté sola en una línea separada. Tan pronto como sqlplus encuentre el carácter especificado como sqlterminator, ignora todo lo demás y deja de leer.

La barra diagonal se puede manejar, siempre que no esté sola en una línea.

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

ejecuta el 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.

No es necesario jugar con los bloques de inicio / finalización. No se puede manejar el comando sqlterminator dentro del comando, sin importar dónde se encuentre, en una cadena o no, no se pueden manejar líneas con barra diagonal sola en una línea de una cadena.


1
Gracias por la prueba Ya estoy usando una configuración de archivo login.sql de manera similar. Básicamente, esto confirma que no puedo hacer por qué me gustaría hacer.
Leigh Riffel

1
una pequeña variación es usar un script de corredor que realice la configuración y llame al script real. Se convertiría en sqlplus leigh / leigh @ orcl @runner leigh. Eso es un poco más flexible que login.sql
ik_zelf

1

Las instrucciones de inserción con líneas en blanco y punto y coma tendrán éxito si se colocan dentro de los bloques BEGIN ... END Este cambio podría hacerse usando un script, pero el script fallaría si contuviera sentencias DDL que no pueden ejecutarse dentro de un bloque sin ejecutarse de inmediato.

Esta solución tampoco resuelve el problema / incrustado.


En el pasado, he usado un script perl / DBD para hacer esto para evitar sqlplus. Feliz de compartir ...
Philᵀᴹ

@ Phil Gracias, pero SQLPlus funciona bien en el 99.9% de las situaciones, por lo que prefiero no agregar otra herramienta a la mezcla.
Leigh Riffel

1

Mi solución alternativa:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Parece que el terminador de comando se ignora dentro de la declaración del cuerpo.


Vea mi respuesta por qué esta no es una buena solución para las declaraciones DDL o las barras inclinadas incrustadas.
Leigh Riffel

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.