in()演算子の制限はすべての悪の根です。
これは些細な場合にも機能し、「準備済みステートメントの自動生成」で拡張できますが、常に制限があります。
- 可変数のパラメーターを持つステートメントを作成している場合、呼び出しごとにSQL解析オーバーヘッドが発生します
- 多くのプラットフォームでは、in()演算子のパラメーターの数が制限されています
- すべてのプラットフォームで、SQLテキストの合計サイズが制限されているため、inパラメータの2000プレースホルダを送信できません。
- JDBCドライバーに制限があるため、1000から10kのバインド変数を送信することはできません。
in()のアプローチは、場合によっては十分ですが、ロケットの証拠にはなりません:)
ロケットに対応するソリューションは、任意の数のパラメーターを個別の呼び出しで渡し(たとえば、パラメーターのCLOBを渡すことにより)、次にSQLでそれらを表すビュー(または他の方法)を使用して、whereで使用することです。基準。
ブルートフォースのバリアントはこちらhttp://tkyte.blogspot.hu/2006/06/varying-in-lists.html
ただし、PL / SQLを使用できる場合は、この混乱はかなりうまくいきます。
function getCustomers(in_customerIdList clob) return sys_refcursor is
begin
aux_in_list.parse(in_customerIdList);
open res for
select *
from customer c,
in_list v
where c.customer_id=v.token;
return res;
end;
次に、パラメーターで任意の数のコンマ区切りの顧客IDを渡すことができます。
- selectのSQLは安定しているため、解析遅延は発生しません
- パイプライン化された関数の複雑さはありません-クエリは1つだけです
- SQLはIN演算子の代わりに単純な結合を使用しており、非常に高速です。
- すべての後に、それはの親指の良いルールではない、それは、Oracle、MySQLや類似したシンプルなデータベースエンジンよりも多くの申し出の光年であることから、任意のプレーンを選択またはDMLを使用してデータベースを打ちます。PL / SQLを使用すると、ストレージモデルをアプリケーションドメインモデルから効果的に隠すことができます。
ここでの秘訣は次のとおりです。
- 長い文字列を受け入れ、dbセッションがアクセスできる場所に格納する呼び出しが必要です(たとえば、単純なパッケージ変数、またはdbms_session.set_context)。
- 次に、これを行に解析できるビューが必要です
- 次に、クエリを実行しているIDを含むビューがあるので、必要なのは、クエリされたテーブルへの単純な結合だけです。
ビューは次のようになります。
create or replace view in_list
as
select
trim( substr (txt,
instr (txt, ',', 1, level ) + 1,
instr (txt, ',', 1, level+1)
- instr (txt, ',', 1, level) -1 ) ) as token
from (select ','||aux_in_list.getpayload||',' txt from dual)
connect by level <= length(aux_in_list.getpayload)-length(replace(aux_in_list.getpayload,',',''))+1
ここで、aux_in_list.getpayloadは元の入力文字列を参照します。
可能なアプローチはpl / sql配列を渡すことです(Oracleのみでサポートされています)。ただし、それらを純粋なSQLで使用することはできないため、変換ステップが常に必要です。SQLで変換を行うことはできないため、結局のところ、すべてのパラメーターを含むCLOBを文字列で渡し、ビューで変換することが最も効率的なソリューションです。