Execute um script com SQLPlus contendo espaços em branco, ponto-e-vírgula e barras

15

Ocasionalmente, recebo um script que funcionará bem no SQL Developer ou no Toad, mas requer modificações para ser executado com êxito no SQL * Plus. Aqui está um exemplo de pior caso, contendo várias instruções, cada uma com linhas em branco, ponto-e-vírgula e barras:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Por vários motivos, essas instruções precisam ser executadas no SQL * Plus. As linhas em branco são fáceis de resolver com um simples ...

set sqlblanklines on

Estou ciente de que o sqlterminatorpode ser alterado e / ou desativado, mas ambos exigiriam modificações no código, o primeiro move o problema sem resolvê-lo e nem resolve o problema da barra incorporada.

A melhor resposta seria uma maneira de permitir que essas instruções sejam executadas sem modificação, alterando o ambiente de alguma maneira (como o sqlblanklines faz). Se isso não for possível, talvez haja uma maneira de modificar programaticamente os scripts. Estou tentando evitar alterações manuais.

Leigh Riffel
fonte
Esse problema pode ocorrer facilmente ao usar a execução de linha de comando do SQLPLUS. Enquanto você estiver dentro do programa SQLPLUS, o editor de linha de comando também estará ativo. Como resultado, itens relevantes para o editor de linha de comando (espaços em branco são interpretados como comando / variável, ponto-e-vírgula é visto como fim de comando). É por isso que ter um '@' em uma senha não causa nada além de sofrimento quando você tenta entrar (tudo à direita de @ é visto como o nome de um banco de dados). Durante uma grande implantação, encontramos problemas com espaços em branco que nos forçaram a implantar coisas através do TOAD. SQLPLUS foi inútil para
TomV
Obrigado por seus pensamentos. Então, para esclarecer sua resposta, o que estou solicitando é impossível?
Leigh Riffel
Você pode converter os retornos de carro na string para que a inserção do chr (10) esteja listada em uma linha?
31812 Chris Saxon
@ ChrisSaxon eu posso, mas esse problema é como distinguir retornos que devem ser codificados e retornos que precisam ser deixados em paz como parte da sintaxe. Se você tem uma maneira de fazer isso, poste-o como resposta.
Leigh Riffel

Respostas:

8

Você pode fazer isso usando um login.sql. O login.sql é executado durante o - surpreendente - login e é carregado a partir do seu SQLPATH ou diretório atual. Para os exemplos que você deu, você realmente escolheu o pior caso.

O problema é o sqlterminator. Tudo o que você coloca lá, a barra é mantida como um sqlterminator gratuito. Além disso, o sqlplus verifica primeiro o sqlterminator e faz isso antes de digitalizar para o terminador de string. Um bug se você me perguntar. A barra para frente pode ser usada em uma string, desde que não esteja sozinha em uma linha separada. Assim que o sqlplus encontra o caractere especificado como sqlterminator, ele ignora todo o resto e para de ler.

A barra para frente pode ser manipulada, desde que não esteja sozinha em uma linha.

login.sql contém:

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 contém:

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

execute o 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.

Não é necessário mexer nos blocos de início / fim. Não pode manipular o sqlterminator dentro do comando, não importa onde esteja, em uma sequência ou não, não pode manipular linhas com barra à frente sozinha em uma linha de uma sequência.

ik_zelf
fonte
11
Obrigado pela prova. Eu já estou usando uma configuração de arquivo login.sql da mesma forma. Então, basicamente, isso confirma que o motivo pelo qual eu gostaria de fazer não pode ser feito.
Leigh Riffel
11
uma pequena variação é usar um script de corredor que faça as configurações e chame o script real. Se tornaria sqlplus leigh / leigh @ orcl @runner leigh. Isso é um pouco mais flexível que o
login.sql
1

Inserir instruções com linhas em branco e ponto-e-vírgula serão bem-sucedidos se colocados dentro dos blocos BEGIN ... END. Essa alteração poderia ser feita usando um script, mas o script falharia se contivesse instruções DDL que não podem ser executadas dentro de um bloco sem serem executadas imediatamente.

Essa solução também não resolve o problema / incorporado.

Leigh Riffel
fonte
No passado, usei um script perl / DBD para fazer isso para evitar o sqlplus. Happy to share ...
Philᵀᴹ
@ Phil Obrigado, mas o SQLPlus funciona bem em 99,9% das situações, então prefiro não adicionar outra ferramenta à mistura.
Leigh Riffel
1

Minha solução alternativa:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Parece que o terminador de comando é ignorado dentro da declaração do corpo.

Bocian
fonte
Veja minha resposta para saber por que essa não é uma boa solução para instruções DDL ou barras incorporadas.
Leigh Riffel
-1
set sqlterminator OFF
<...>
set sqlterminator ON
user28627
fonte
11
E como isso vai ajudar?
Dezso