in() 演算子の制限はすべての悪の根源です。
些細なケースで機能し、「準備されたステートメントの自動生成」で拡張できますが、常に制限があります。
- 可変数のパラメーターを持つステートメントを作成している場合、呼び出しごとに sql 解析のオーバーヘッドが発生します
- 多くのプラットフォームでは、in() 演算子のパラメーターの数が制限されています
- すべてのプラットフォームで、SQL テキストの合計サイズが制限されているため、in パラメーターの 2000 個のプレースホルダーを送信することは不可能です。
- JDBC ドライバーには制限があるため、1000 ~ 10k のバインド変数を送信することはできません。
in() アプローチは、場合によっては十分ですが、ロケットプルーフではありません:)
ロケットプルーフのソリューションは、別の呼び出しで任意の数のパラメーターを渡し (たとえば、params の塊を渡すことにより)、ビュー (またはその他の方法) を使用してそれらを 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 演算子の代わりに単純な結合を使用しています。これは非常に高速です。
- 結局のところ、単純な select または DML でデータベースにアクセスしないのは経験則として適切です。なぜなら、MySQL や同様の単純なデータベース エンジンよりも何光年も多くを提供するのは Oracle だからです。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 を渡し、それをビュー内で変換するのが最も効率的なソリューションです。