SQLのIN句の制限まとめ：SQL Server・OracleDB・PostgreSQLの違い

## 概要

SQLの`IN`句は、複数の値を指定して条件を絞り込む際に便利ですが、データベースごとに使用できる要素数や制約が異なります。本記事では、SQL Server、Oracle Database、PostgreSQLの`IN`句の制限を比較し、各データベースの仕様と回避策について解説します。

## IN句の制限・仕様比較

| データベース | IN句の最大要素数 | 主な制約 | 仕様に関する公式情報 | 制約に関する公式情報 |
|-------------|-----------------|------------|----------------|----------------|
| **SQL Server** | 明確な制限なし | クエリが複雑化すると **エラー 8623, 8632** の発生リスクあり | [IN 句 (公式)](https://learn.microsoft.com/ja-jp/sql/t-sql/language-elements/in-transact-sql) | [エラー 8623](https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-8623-database-engine-error), [エラー 8632](https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-8632-database-engine-error) |
| **OracleDB** | 最大1,000個 | **ORA-01795** が発生し、それ以上の要素は使用不可 | [IN 条件 (公式)](https://docs.oracle.com/cd/F39414_01/sqlrf/IN-Condition.html) | [ORA-01795](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Restrictions-on-DML-Statements.html) |
| **PostgreSQL** | 明確な制限なし | メモリ使用量や実行計画の影響でパフォーマンス低下の可能性あり | [テーブル式 (公式)](https://www.postgresql.org/docs/current/queries-table-expressions.html) | [パフォーマンスガイド](https://www.postgresql.org/docs/current/performance-tips.html) |

## 各データベースの詳細

### SQL Server
#### 仕様
SQL Serverでは、`IN`句の要素数に明確な上限はありません。しかし、リストが長くなるとメモリ使用量が増加し、クエリの実行計画が複雑化するため、パフォーマンスに影響を与える可能性があります。([IN 句 (公式)](https://learn.microsoft.com/ja-jp/sql/t-sql/language-elements/in-transact-sql))

#### 制約
- `IN`句に大量の要素を指定すると、**エラー 8623（クエリプロセッサのリソース制約）やエラー 8632（メモリ不足によるソート演算子の失敗）** の発生リスクがあります。
([エラー 8623](https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-8623-database-engine-error), [エラー 8632](https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-8632-database-engine-error))

#### 回避策
- `JOIN`を使用し、別のテーブルからデータを取得する。
- 一時テーブルやテーブル変数を活用する。
- `EXISTS` を活用してフィルタリングする。

### OracleDB
#### 仕様
Oracle Databaseでは、`IN`句の要素数が**最大1,000個**までと明確に制限されています。([IN 条件 (公式)](https://docs.oracle.com/cd/F39414_01/sqlrf/IN-Condition.html))

#### 制約
- `IN`句の要素数が最大1,000個を超えると、**ORA-01795: maximum number of expressions in a list is 1000** というエラーが発生します。
([ORA-01795](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Restrictions-on-DML-Statements.html))

#### 回避策
- `GLOBAL TEMPORARY TABLE` を使用してデータを一時的に保存する。
- `WITH` 句を活用して処理する。
- `TABLE` 関数を利用し、配列として扱う。
- `OR` を使って最大1,000個ごとにクエリを分割する。

### PostgreSQL
#### 仕様
PostgreSQLでは、`IN`句の要素数に明確な制限はありません。ただし、クエリの最適化や実行計画の影響により、大量の要素を含む`IN`句はパフォーマンスの低下を引き起こす可能性があります。([テーブル式 (公式)](https://www.postgresql.org/docs/current/queries-table-expressions.html))

#### 制約
- 明確な要素数の上限はありませんが、**メモリ使用量の増加や実行計画の最適化不足により、パフォーマンスが低下する可能性があります**。
([パフォーマンスガイド](https://www.postgresql.org/docs/current/performance-tips.html))

#### 回避策
- `JOIN` やサブクエリを活用する。
- `ARRAY` を使用してリストを効率的に処理する。

## **余談：SQL Server の `INSERT ... VALUES` にも 1000 件の制限がある**

OracleDB は `IN` 句が **最大1,000個** の制限がありますが、SQL Server では `INSERT ... VALUES` で **1回の挿入は 1000 行まで** という制約があります。

- **SQL Server**: `INSERT ... VALUES` の形式では 1000 行を超えると **エラー 10738** が発生。
- **OracleDB, PostgreSQL** にはこのような `INSERT ... VALUES` の行数制限はなし。
- **回避策として `INSERT ... SELECT` などを活用するのが推奨される。**

このように、「1000」という制約が SQL Server では `INSERT`、OracleDB では `IN` 句に適用されるため、混同しがちなので注意しましょう。