ORA-01795 : リストに指定できる式の最大数は1000です。 の原因と対処方法

  • URLをコピーしました!

Oracle Database を利用していると、SQL 実行時に
ORA-01795 : リストに指定できる式の最大数は1000です。
というエラーが発生することがあります。

このエラーは一見すると分かりにくいものの、原因は明確で、発生条件も限られています。
しかし、業務システムやバッチ処理などで大量データを扱う場面では非常に起こりやすく、適切な対処方法を理解していないと、無理な修正やパフォーマンス低下を招く恐れがあります。

本記事では、ORA-01795 が発生する正確な原因と、現場でよく使われる対処方法を、実務目線で分かりやすく解説します。

IN 句に 1000 件以上指定してエラーが出ている SQL 実行画面

目次

ORA-01795 エラーとは何か

ORA-01795 は、IN 句などのリスト指定において、1000 個を超える式を指定した場合に発生する Oracle 固有の制限エラーです。

Oracle Database では、SQL 文の中で以下のような書き方をした場合、
1つのリストに指定できる値の上限は 1000 個まで
という制限が設けられています。

SELECT *
FROM employees
WHERE employee_id IN (1, 2, 3, ..., 1001);

このように、IN 句の中に 1001 個以上の値を並べると、SQL は実行前にエラーとして拒否され、ORA-01795 が返されます。


エラーが発生する主な原因

ORA-01795 が発生する原因は、ほぼ以下のケースに集約されます。

1. IN 句に 1000 件を超える値を指定している

最も典型的な原因です。
アプリケーション側で取得した ID リストや、バッチ処理で生成した配列をそのまま SQL に渡している場合に発生しやすくなります。

特に以下のようなケースでは注意が必要です。

  • CSV やファイルから読み込んだ ID をそのまま IN 句に展開している
  • 画面検索条件で大量のチェックボックス選択を許可している
  • サブシステムから受け取った ID リストを加工せずに使用している

2. サブクエリの結果が 1000 件を超えている(誤解されやすい点)

ORA-01795 は サブクエリの結果件数が 1000 件を超えた場合に直接発生するわけではありません

ただし、以下のように サブクエリの結果をアプリ側で展開し、IN 句として再利用している場合はエラーになります。

WHERE col IN (:id1, :id2, :id3, ...);
Code language: CSS (css)

サブクエリ自体が原因ではなく、「最終的に SQL 文として 1000 件超のリストになっている」ことが原因です。

3. フレームワークや ORM が内部的に IN 句を生成している

Java + MyBatis、Hibernate、Spring JDBC などを使用している場合、
コレクションをそのままバインドすると、内部的に IN 句へ展開されます。

開発者が直接 SQL を書いていなくても、結果的に 1000 件超の IN 句が生成され、ORA-01795 が発生することがあります。

なお、Oracle では IN 句や WHERE 句の書き方を誤った場合、
ORA-01795 とは別に構文エラーが発生することもあります。
特に多いのが、条件式の不足や記述ミスによって発生する
「ORA-00936: 式がありません」エラーです。

SQL の具体的な誤り例と修正方法については、
以下の記事で詳しく解説しています。


ORA-01795 の代表的な対処方法

ここからは、実務でよく採用される対処方法を具体的に解説します。


対処方法1:IN 句を分割して OR 条件でつなぐ

最も単純で、緊急対応として使われる方法です。

WHERE col IN (1~1000)
   OR col IN (1001~2000)

1000 件以内に分割することで、エラーを回避できます。

メリット

  • 実装が簡単
  • 既存 SQL の修正量が少ない

デメリット

  • SQL が長くなり、可読性が低下する
  • 条件が増えるとパフォーマンスに影響が出る可能性がある

対処方法2:一時表(グローバル一時表)を使用する

大量データを扱う場合に、最も推奨される方法です。

  1. ID を一時表に INSERT
  2. JOIN で参照する
SELECT t.*
FROM target_table t
JOIN temp_ids i ON t.id = i.id;

メリット

  • 件数制限を受けない
  • パフォーマンスが安定しやすい
  • SQL がシンプルになる

デメリット

  • 一時表の管理が必要
  • トランザクション設計に注意が必要

対処方法3:サブクエリを直接使用する

IN 句に直接値を並べるのではなく、サブクエリとして記述します。

WHERE col IN (
  SELECT id
  FROM another_table
);

この書き方では 1000 件制限は適用されません

注意点

  • サブクエリのパフォーマンスに注意
  • 実行計画の確認は必須

対処方法4:EXISTS 句に書き換える

IN 句の代替として EXISTS を使用する方法です。

WHERE EXISTS (
  SELECT 1
  FROM temp_ids t
  WHERE t.id = main.id
);

メリット

  • 件数制限なし
  • 大量データに強い

デメリット

  • 書き方に慣れが必要
  • 実行計画の理解が求められる

対処方法5:アプリケーション側で制御する

  • 1000 件ごとに分割して SQL を発行
  • バッチ処理としてループ処理を行う

即効性はありますが、設計としては最後の手段です。


ORA-01795 を回避する設計上の注意点

  • 大量データを IN 句で処理しない
  • ID リストは表として扱う
  • 将来的な件数増加を考慮する
  • ORM 任せにしないで、生成される SQL を必ず確認する

よくある質問(Q & A)

Oracle のバージョンによって制限は変わりますか?

いいえ。Oracle Database では長年この制限は変わっていません。

サブクエリでも 1000 件制限はありますか?

サブクエリ自体には制限はありません。IN 句に直接値を列挙した場合のみ制限されます。

1000 件ちょうどなら問題ありませんか?

はい。1000 件までは問題なく実行できます。

パフォーマンス面で最もおすすめの対処法は?

一時表を使用した JOIN が最も安定します。

EXISTS と IN はどちらが良いですか?

データ量が多い場合は EXISTS の方が有利になるケースが多いです。


まとめ

ORA-01795 は Oracle の仕様による制限であり、バグではありません。
原因を正しく理解すれば、回避方法はいくつも存在します。

特に、大量データを扱うシステムでは IN 句に値を並べる設計自体を見直すことが重要です。
一時表や JOIN、EXISTS を活用し、将来的な拡張にも耐えられる SQL 設計を行いましょう。

よかったらシェアしてね!
  • URLをコピーしました!
0 0
Article Rating
申し込む
注目する
guest
0 コメント一覧
最も古い
最新 高評価
インラインフィードバック
すべてのコメントを見る
目次
0
あなたの考えが大好きです、コメントしてください。x