【Oracle】IN句の上限を回避する方法

OracleのIN句には、1,000項目までという制限があります。これをどうしても回避したいケースがあったので、回避方法を紹介します。

複合条件を使用する

SELECT * FROM table WHERE (アイテム, 1) IN (('AAA', 1), ('BBB', 1), ..., ('ZZZ', 1))

(‘値’, ダミーの値)とすることで上限を回避することが可能です。上記の場合、’AAA’や’BBB’が実際の条件として指定する値で1はダミーの値となります。

お手軽ですが、これにも落とし穴があり、65,535件より多くなるとエラー(ORA-00913: 値の個数が多すぎます)となってしまいます。

複数のIN句を使う

SELECT * FROM table WHERE column IN (val1, val2, ..., val1000)
OR column IN (val1001, val1002, ..., val2000);

1,000項目ごとに分割してORで繋ぎます。

UNION ALLを使用

SELECT * FROM table WHERE column IN (val1, val2, ..., val1000)
UNION ALL
SELECT * FROM table WHERE column IN (val1001, val1002, ..., val2000);

クエリを分割してUNION ALLで結合します。

EXISTS句を使用

SELECT * FROM main_table mt
WHERE EXISTS (
    SELECT 1 FROM other_table ot
    WHERE mt.A = ot.valA AND mt.B = ot.valB
);

条件に使用する値が別のテーブルに保存されている場合は、EXISTS句を使用することで、IN句の制限を回避することができます。特に、サブクエリを使用する場合に便利です。

他の方法に比べると処理も軽いので、使用できるのであればおすすめです。