Выполните сценарий с SQLPlus, содержащий пробелы, точки с запятой и косую черту


15

Иногда я получаю сценарий, который будет нормально работать в SQL Developer или Toad, но требует модификации для успешного запуска из SQL * Plus. Вот пример наихудшего случая, содержащий несколько операторов, каждое из которых содержит пустые строки, точки с запятой и косую черту:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

По разным причинам эти операторы должны запускаться из SQL * Plus. Пустые строки легко решить с помощью простого ...

set sqlblanklines on

Я знаю, что их sqlterminatorможно изменить и / или отключить, но оба требуют изменения кода, первый перемещает проблему, не решая ее, и не решает проблему встроенной косой черты.

Наилучшим ответом был бы способ разрешить выполнение этих операторов без изменений, изменяя каким-либо образом среду (как это делает sqlblanklines). Если это невозможно, возможно, есть способ программно изменить сценарии. Я пытаюсь избежать ручных изменений.


Эта проблема может легко возникнуть при использовании командной строки SQLPLUS. Пока вы находитесь внутри программы SQLPLUS, редактор командной строки также все еще активен. В результате элементы, которые имеют отношение к редактору командной строки (пробелы интерпретируются как команда / переменная, точки с запятой рассматриваются как конец команды). Вот почему наличие «@» в пароле не вызывает ничего, кроме душевной боли, когда вы пытаетесь войти (все справа от @ рассматривается как имя БД). Во время крупного развертывания мы обнаружили проблемы с пробелами, которые вынуждали нас развертывать вещи через TOAD. SQLPLUS был бесполезен для
TomV

Спасибо за ваши мысли. Итак, чтобы уточнить ваш ответ, что то, что я запрашиваю, невозможно?
Ли Риффель

Можете ли вы преобразовать возврат каретки внутри строки в строку вставки chr (10) в одну строку?
Крис Саксон

@ChrisSaxon Я могу, но эта проблема заключается в том, как различить возвращаемые значения, которые должны быть закодированы, и возвращаемые данные, которые необходимо оставить в одиночестве как часть синтаксиса. Если у вас есть способ сделать это, пожалуйста, опубликуйте это как ответ.
Ли Риффель

Ответы:


8

Вы можете сделать большую часть этого, используя login.sql. login.sql выполняется во время - удивительно - входа в систему и загружается из вашего SQLPATH или текущего каталога. Для приведенных вами примеров вы действительно выбрали худший вариант.

Проблема в том, что sqlterminator. Что бы вы там ни указали, косая черта поддерживается как бесплатный sqlterminator. Кроме того, sqlplus сначала сканирует sqlterminator и делает это перед сканированием до строкового терминатора. Ошибка, если вы спросите меня. Косая черта может использоваться в строке, если она не одинока в отдельной строке. Как только sqlplus находит символ, указанный как sqlterminator, он игнорирует все остальное и прекращает чтение.

Косая черта может быть обработана, пока она не одна на линии.

login.sql содержит:

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 содержит:

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

запустите скрипт:

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.

Не нужно возиться с блоками начала / конца. Не может обрабатывать sqlterminator внутри команды, независимо от того, где она находится, в строке или нет, не может обрабатывать строки с косой чертой в строке в строке.


1
Спасибо за доказательство. Я уже использую настройки файла login.sql аналогичным образом. Так что в основном это подтверждает, что то, чего я хотел бы сделать, не может быть сделано.
Ли Риффель

1
Небольшое изменение заключается в использовании скрипта бегуна, который выполняет настройки и вызывает реальный скрипт. Станет sqlplus leigh / leigh @ orcl @runner leigh. Это немного более гибко, чем login.sql
ik_zelf

1

Операторы вставки с пустыми строками и точками с запятой завершатся успешно, если поместить их в блоки BEGIN ... END. Это изменение может быть выполнено с использованием сценария, но сценарий завершится ошибкой, если он содержит операторы DDL, которые нельзя выполнить внутри блока без немедленного выполнения.

Это решение также не решает внедренную проблему.


В прошлом я использовал скрипт perl / DBD, чтобы избежать sqlplus.
Рад

@Phil Спасибо, но SQLPlus отлично работает в 99,9% случаев, поэтому я бы не стал добавлять в этот инструмент другой инструмент.
Ли Риффель

1

Мой обходной путь:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

Кажется, что терминатор команды игнорируется внутри оператора body.


См. Мой ответ, почему это не очень хорошее решение для операторов DDL или встроенных слешей.
Ли Риффель

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.