空白、セミコロン、およびスラッシュを含む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プログラム内では、コマンドラインエディターもアクティブです。その結果、コマンドラインエディターに関連する項目(空白スペースはコマンド/変数として解釈され、セミコロンはコマンドの終わりと見なされます)。そのため、パスワードに「@」が含まれていると、サインインしようとすると心痛しか生じません(@の右側はすべてDBの名前と見なされます)。主要な展開中に、TOADを介してスタッフを展開することを余儀なくされる空白の問題を発見しました。SQLPLUSは役に立たなかった
TomV

ご意見ありがとうございます。それで、明確にすることは、私が要求していることは不可能であるというあなたの答えですか?
リーリフェル

文字列内のキャリッジリターンをchr(10)の挿入に変換できますか?
クリスサクソン

@ChrisSaxonできますが、この問題は、エンコードする必要があるリターンと、構文の一部としてそのままにする必要があるリターンを区別する方法です。これを行う方法がある場合は、これを回答として投稿してください。
リーリッフェル

回答:


8

これのほとんどは、login.sqlを使用して実行できます。login.sqlは、驚くべきことにログイン中に実行され、SQLPATHまたは現在のディレクトリからロードされます。あなたが与えた例については、あなたは本当に最悪のケースを選択しました。

問題はsqlterminatorです。そこに何を入れても、スラッシュは無料のsqlterminatorとして維持されます。その次に、sqlplusは最初にsqlterminatorをスキャンし、これを実行してから文字列ターミネーターにスキャンします。あなたが私に尋ねるとバグ。スラッシュは、単独の行にない限り、文字列で使用できます。sqlplusがsqlterminatorとして指定された文字を見つけると、すぐに他のすべてを無視し、読み取りを停止します。

スラッシュは、1行にない限り処理できます。

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ᵀᴹ

@Philありがとうございます。しかし、SQLPlusは99.9%の状況でうまく動作するので、別のツールをミックスに追加したくありません。
リーリフェル

1

私の回避策:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

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


これがDDLステートメントや埋め込みスラッシュの良い解決策ではない理由については私の答えをご覧ください。
リーリッフェル

-1
set sqlterminator OFF
<...>
set sqlterminator ON

1
そして、これはどのように役立ちますか?
-dezso
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.