web-dev-qa-db-ja.com

ブランク、セミコロン、スラッシュを含むSQLPlusでスクリプトを実行します。

ときどき、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が行うように)これらのステートメントを変更せずに実行できるようにする方法です。それが不可能な場合は、スクリプトをプログラムで変更する方法が考えられます。手動で変更しないようにしています。

15
Leigh Riffel

これのほとんどは、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を処理できません。文字列のどこにあるかに関わらず、文字列の行でスラッシュのみの行は処理できません。

8
ik_zelf

私の回避策:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

コマンドターミネータがbodyステートメント内で無視されているようです。

1
Bocian

空白行とセミコロンを含むステートメントを挿入すると、BEGIN ... ENDブロック内に配置すると成功します。この変更はスクリプトを使用して行うことができますが、即時実行せずにブロック内で実行できないDDLステートメントがスクリプトに含まれている場合、スクリプトは失敗します。

このソリューションでは、埋め込み/問題も解決されません。

1
Leigh Riffel