Exécuter un script avec SQLPlus contenant des espaces, des points-virgules et des barres obliques


15

Parfois, j'obtiendrai un script qui fonctionnera correctement dans SQL Developer ou Toad, mais qui nécessite une modification pour être exécuté avec succès à partir de SQL * Plus. Voici le pire exemple contenant plusieurs instructions, chacune avec des lignes vides, des points-virgules et des barres obliques:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Pour diverses raisons, ces instructions doivent être exécutées à partir de SQL * Plus. Les lignes blanches sont faciles à résoudre avec un simple ...

set sqlblanklines on

Je suis conscient que le sqlterminatorpeut être modifié et / ou désactivé, mais les deux nécessiteraient des modifications du code, le premier déplace le problème sans le résoudre et aucun ne résout le problème de la barre oblique intégrée.

La meilleure réponse serait de permettre à ces instructions de s'exécuter sans modification en modifiant l'environnement d'une manière ou d'une autre (comme le fait sqlblanklines). Si cela n'est pas possible, il existe peut-être un moyen de modifier par programme les scripts. J'essaie d'éviter les changements manuels.


Ce problème peut facilement se produire lors de l'utilisation de l'exécution en ligne de commande de SQLPLUS. Pendant que vous êtes dans le programme SQLPLUS, l'éditeur de ligne de commande est également toujours actif. Par conséquent, les éléments pertinents pour l'éditeur de ligne de commande (les espaces vides sont interprétés comme commande / variable, les points-virgules sont considérés comme la fin de la commande). C'est pourquoi avoir un «@» dans un mot de passe ne provoque que du chagrin lorsque vous essayez de vous connecter (tout à droite de @ est considéré comme le nom d'une base de données). Lors d'un déploiement majeur, nous avons trouvé des problèmes avec des espaces vides qui nous ont obligés à déployer des choses via TOAD. SQLPLUS était inutile pour
TomV

Merci pour vos pensées. Donc, pour clarifier est votre réponse que ce que je demande est impossible?
Leigh Riffel

Pouvez-vous convertir les retours chariot dans la chaîne en insert chr (10) s est répertorié sur une seule ligne?
Chris Saxon

@ChrisSaxon Je peux, mais ce problème est de savoir comment distinguer les retours qui doivent être encodés et les retours qui doivent être laissés seuls dans le cadre de la syntaxe. Si vous avez un moyen de le faire, veuillez poster ceci comme réponse.
Leigh Riffel

Réponses:


8

Vous pouvez faire la plupart de cela en utilisant un login.sql. login.sql est exécuté lors de la connexion - surprenante - et est chargé à partir de votre répertoire SQLPATH ou actuel. Pour les exemples que vous avez donnés, vous avez vraiment choisi le pire des cas.

Le problème est le sqlterminator. Quoi que vous y mettiez, la barre oblique est conservée comme un sqlterminator gratuit. À côté de cela, sqlplus recherche d'abord le sqlterminator et le fait avant de numériser vers le terminateur de chaîne. Un bug si vous me demandez. La barre oblique peut être utilisée dans une chaîne tant qu'elle n'est pas seule sur une ligne séparée. Dès que sqlplus trouve le caractère spécifié comme sqlterminator, il ignore tout le reste et arrête la lecture.

La barre oblique peut être gérée, tant qu'elle n'est pas seule sur une ligne.

login.sql contient:

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

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

exécutez le 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.

Pas besoin de jouer avec les blocs de début / fin. Impossible de gérer sqlterminator à l'intérieur de la commande, peu importe où il se trouve, dans une chaîne ou non, ne peut pas gérer les lignes avec barre oblique seule sur une ligne dans une chaîne.


1
Merci pour la preuve. J'utilise déjà une configuration de fichier login.sql de la même manière. Donc, fondamentalement, cela confirme que la raison pour laquelle je voudrais faire ne peut pas être faite.
Leigh Riffel

1
une petite variation consiste à utiliser un script runner qui fait les paramètres et appelle le vrai script. Deviendrait sqlplus leigh / leigh @ orcl @runner leigh. C'est un peu plus flexible que login.sql
ik_zelf

1

Les instructions d'insertion avec des lignes vides et des points-virgules réussiront si elles sont placées à l'intérieur des blocs BEGIN ... END. Cette modification pourrait être effectuée à l'aide d'un script, mais le script échouerait s'il contenait des instructions DDL qui ne peuvent pas être exécutées à l'intérieur d'un bloc sans exécution immédiate.

Cette solution ne résout pas non plus le problème intégré /.


Dans le passé, j'ai utilisé un script perl / DBD pour éviter cela sqlplus. Heureux de partager ...
Philᵀᴹ

@Phil Merci, mais SQLPlus fonctionne très bien dans 99,9% des situations, donc je préfère ne pas ajouter un autre outil au mix.
Leigh Riffel

1

Ma solution:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Il semble que le terminateur de commande soit ignoré dans l'instruction body.


Voir ma réponse pour savoir pourquoi ce n'est pas une bonne solution pour les instructions DDL ou les barres obliques intégrées.
Leigh Riffel

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.