web-dev-qa-db-ja.com

テーブル名にOracleスクリプトで変数を使用する方法

スクリプトで使用されるテーブル名を変数に設定するpl\sqlスクリプトがあります。それで、私がウェブで見つけたいくつかの例から、私は以下のコードを書きました。最初のセクションは機能するので、私の一般的な構文は正しいと思いますが、2番目のセクションでは、テーブル名に変数を使用しようとすると、エラーになります( "SQLエラー:ORA-00903:無効なテーブル名 = ")。

誰かが私が間違っていることを知っています...私は多くのPL\SQLをしないので、多分私は明白な何かを見逃しているだけかもしれません。

--works
variable numOfrecords number;
exec :numOfrecords := 10;
select * from customers2008 where rownum < :numOfrecords;

--does not work
 variable tableNm CHAR;
 exec :tableNm := 'customers2008';
 print tableNm;
 select * from :tableNm;
15
Gern Blanston

このスクリプトをsqlplus(そうであるように見えます)から実行している場合、DEFINEコマンドを使用すると、単なる文字列置換であるsqlplus置換変数を作成できます。例:

define tableNm = 'customers2008'
select * from &tableNm;

これらの使用方法の詳細については、 sing Sql * Plus を参照してください。次のように、事前定義された位置置換変数を使用して、コマンドラインからスクリプトに値を渡すことができます。

define tableNm = &1
select * from &tableNm;

...次に、sqlplusを次のように呼び出します。

sqlplus user/pwd@server @myscript.sql customers2008

コマンドラインで値を渡さない場合、スクリプト呼び出し元は値の入力を求められます。

バインド変数と置換変数の違いについては、以下のDave Costaの回答を参照してください。

15
Steve Broberg

説明を追加しようとするには:

使用しようとしていたメソッドはバインド変数と呼ばれます。 Oracle SQLでは、バインド変数は、コロンとそれに続く識別子で識別されます。バインド変数の目的は、SQL文を解析するときにその値を知る必要がないことです。ステートメントは1回解析され、変数にバインドされたさまざまな値を使用して複数回実行されます。

SQLステートメントを解析するには、関連するテーブルと列の名前がわかっている必要があります。したがって、値は解析時に認識されないため、テーブル名をバインド変数で表すことはできません。

スティーブが説明したように、単にSQLとインラインPL/SQlをSQLPlus経由で実行している場合、置換変数はこの問題に対処する簡単な方法です。置換変数は、SQLPlusクライアントがコマンドを読み取るときに、解析のためにOracleに送信する前に、その値に置き換えられます。

8
Dave Costa

あなたはこのようなことをしなければなりません:

EXECUTE IMMEDIATE 'select * from' || tableNm;

これは、Oracleがテーブル(またはその他のオブジェクト名)のバインド変数を許可しないためです。

EXECUTE IMMEDIATEアプローチには、重大なセキュリティ上の影響があります。tableNm値がユーザー指定である場合、 SQLインジェクション 攻撃に広く開放されます。

7
Arkady

置換変数 作業:

SQL> select * from &table_name;
Enter value for table_name: dual
old   1: select * from &table_name
new   1: select * from dual

D
-
X
6
Eddie Awad