it-swarm-eu.dev

Spusťte skript s SQLPlus obsahující mezery, středníky a lomítka

Občas dostanu skript, který bude fungovat dobře v SQL Developer nebo Toad, ale vyžaduje úpravy, aby mohl být úspěšně spuštěn z SQL * Plus. Zde je nejhorší příklad obsahující více příkazů, každý s prázdnými řádky, středníky a lomítky:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

Z různých důvodů je třeba tyto příkazy spouštět z SQL * Plus. Prázdné řádky lze snadno vyřešit jednoduchým ...

set sqlblanklines on

Jsem si vědom toho, že sqlterminator lze změnit a/nebo vypnout, ale obojí by vyžadovalo úpravy kódu, ten první přesune problém, aniž by jej vyřešil, ani nevyřeší problém s vloženým lomítkem.

Nejlepší odpovědí by byl způsob, jak těmto příkazům umožnit běžet beze změn změnou prostředí nějakým způsobem (stejně jako sqlblanklines). Pokud to není možné, pak existuje způsob, jak skripty programově upravit. Snažím se vyhnout manuálním změnám.

15
Leigh Riffel

Většinu z toho můžete udělat pomocí login.sql. login.sql je spuštěn během - překvapivé - přihlášení a je načten z vašeho SQLPATH nebo aktuálního adresáře. Pro příklady, které jste uvedli, si váš opravdu vybral nejhorší případ.

Problém je sqlterminator. Ať už to vložíte cokoli, přední lomka je udržována jako volný sqlterminátor. Kromě toho sqlplus nejprve vyhledá sqlterminator a provede to před skenováním do terminátoru řetězců. Chyba, pokud se mě zeptáte. Přední lomítko lze použít v řetězci, pokud není na samostatné lince samostatně. Jakmile sqlplus najde znak specifikovaný jako sqlterminator, ignoruje všechno ostatní a zastaví čtení.

S lomítkem lze manipulovat, pokud není na řádku sám.

login.sql obsahuje:

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

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

spusťte skript:

sqlplus leigh/[email protected] @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.

Není třeba se hádat s počátečními/koncovými bloky. Nelze zpracovat příkaz sqlterminator uvnitř příkazu, bez ohledu na to, kde je, v řetězci nebo ne, nemůže zvládnout řádky s lomítkem pouze na řádku v řetězci.

8
ik_zelf

Moje řešení:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Vypadá to, že terminátor příkazů je uvnitř příkazu body ignorován.

1
Bocian

Vložení příkazů s prázdnými řádky a středníky bude úspěšné, pokud budou umístěny uvnitř bloků BEGIN ... END. Tuto změnu lze provést pomocí skriptu, ale skript by selhal, pokud by obsahoval příkazy DDL, které nelze spustit uvnitř bloku bez provedení okamžitého spuštění.

Toto řešení také nevyřeší vložený problém.

1
Leigh Riffel