web-dev-qa-db-ja.com

ファイル経由のSQLPlusパラメータ化クエリ

テキストファイルで提供されるすべてのパラメーターを使用して、sqlplus経由でパラメーター化されたOracleを発行したいと思います。これを行う方法はありますか?クエリには、ユーザーにプロンプ​​トが表示されるのに妥当な数よりも多くのパラメーターがあり、このパラメーターを入力するときのユーザーエラーを排除したいと考えています。

パラメータ化されたクエリを発行する必要がある理由は、単純なSQLステートメントと、アプリケーションでパラメータ化されたクエリとして発行された同じクエリのパフォーマンスに大きな違いがあるためです。チェーンからアプリケーションコードを削除し、Oracleツールのみで違いを明らかにしたいと思います。

5
Darryl Braaten

SQLを1つのファイルに、パラメーターを別のファイルにしたい場合、これはオプションです。 query.sqlに位置変数を割り当てて変数をバインドし、クエリを実行します。

variable p_owner varchar2(30);
variable p_column varchar2(30);

set verify off
set feedback off

begin
    :p_owner := '&1';
    :P_column := '&2';
end;
/

set feedback on

select table_name
from all_tab_columns
where owner = :p_owner
and column_name = :p_column;

exit 0;

そして、パラメータ値をテキストファイルに入れます。たとえば、parms.txt

SYS
OSUSER

そしてそれを一緒に入れます:

sqlplus -s user/password @query `cat parms.txt`

(これは明らかにUnixの場合です。同等のコマンドラインがWindowsの場合は、手元ではわかりません)。 parms.txtを変更するか、別のファイルを使用すると、毎回同じハード解析されたプランが引き続き得られます。

パフォーマンスの問題は、バインド変数のピーク、特に「悪い計画で立ち往生」の説明に関連している可能性があるようです。実行プランは、最初のクエリの実行によって決定され、これらのパラメーターに適切なインデックスなどが選択される場合があります。その後の実行では、異なるパラメーターが新しいパラメーターに適している場合でも、同じプランを使用します。スタンドアロンのストレートSQLには個別の解析があり、したがって異なる(より適切な)プランになる可能性があります。過去には、ヒストグラムを使用しないように統計を手動で収集する必要がありました。

5
Alex Poole

さて、パラメーター化されたクエリは、より良い結果をもたらします。これに似た方法を使用する方法は、UTLFILEを使用してパラメーターを開いて読み取る無名PL/SQLブロックを使用し、パラメーターをブロック内のクエリにフィードして、出力をファイルシステムに書き戻すことでした。

もちろんYMMV。

4
mezmo

SQL Plusについて言及しているので、コマンドラインでこれを行っていると思いますか?もしそうなら、これはあなたのために働くかもしれません:

parms.shl:
export parm1=1
export parm2=15
export parm3=150

dojob.shl:
#!/bin/sh
# source our variables into our context.
. parms.shl 
# call sqlplus and have the variables embedded.
sqlplus -s <<EOF
-- we're now in SQLPLUS
SELECT '$parm1', '$parm2', '$parm3'
  FROM DUAL;
-- and exit out
EXIT;
EOF

次に、コマンドプロンプトで次のコマンドを実行します。

./dojob.shl

そして、結果は入力パラメータと一致するはずです。問題は、SQLがシェルスクリプト内にある必要があることです。 (sqlplusの@ filename.sql機能を使用しても、OSレベルの環境変数は表示されません。)

最もエレガントではありませんが、UTF_FILEオーバーヘッド/リスクなしで機能します。ほとんどの* NIX/BSDバリアントで動作するはずですが、Windowsバッチファイルに変換するのは難しくありません。

補足:データを保存する準備ができている場所にパラメータを保存してみませんか?つまり、データベースですか?パラメータを変更可能にする必要がある場合は、エンドユーザーがパラメータを更新できる画面または他のプロセスを記述し、プロセス内のテーブルにリンクするだけです。

サイドサイド注:この例では、変数のバインドに関して何もしていません。したがって、実行時間の長いステートメントで使用すると、パフォーマンスはそれほど向上しません。 sqlplusの変数を使用して、影響を軽減することができます(VARIABLEを介して変数をOS変数に設定してから、実際のコードでsqlplusの変数を再利用します。その後、Oracleはステートメントを適切に最適化できるはずです。 http:/ /www.adp-gmbh.ch/ora/sqlplus/use_vars.html

3
Kerri Shotts

名前付きパラメーターownerおよびtableをファイルparams.sqlに定義します。

    define owner=scott
    define table=emp

定義ファイルを呼び出し、ファイルquery.sqlのパラメーターを使用します

    @params.sql
    select count(*) from &owner..&table
    /
    exit

..の後の&owner(2つのドット)は意図されています。

params.sqlquery.sqlがあるディレクトリに移動して、

    sqlplus user/password@database @query.sql

名前付きパラメーターは、SQLのコマンドラインパラメーターと同じ方法でファイルquery.sqlで使用できますプラス。ファイルparams.sqlには、define以外のステートメントを含めることができます。 SQL * plusマニュアルで説明されているSQL Plusで使用できる多くのテクニックです。

2
miracle173