본문 바로가기
DataBase/Oracle

Oracle ORA-01795 에러 – IN 절 1000개 초과 시 발생하는 SQLSyntaxErrorException

by 호호호호히히히히 2025. 6. 17.
728x90
반응형

Oracle ORA-01795 에러 – IN 절 1000개 초과 시 발생하는 SQLSyntaxErrorException

1. 에러 개요

Spring 기반 애플리케이션에서 Oracle DB 쿼리를 실행하는 도중 아래와 같은 예외가 발생했습니다.

org.springframework.jdbc.BadSqlGrammarException:
### Error querying database.
Cause: java.sql.SQLSyntaxErrorException: ORA-01795: maximum number of expressions in a list is 1000
### The error may exist in URL [jar:file:/app.jar!/BOOT-INF/classes!/mapper/example-mapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters

2. 원인

Oracle의 IN 절은 최대 1000개의 항목만 허용합니다. 이 제약을 초과할 경우 SQL 문이 무효로 간주되어 SQLSyntaxErrorException이 발생합니다.

3. 문제 쿼리 예시

SELECT item.COL1, item.COL2, test.COL3
FROM [TABLE]_ITEM item
RIGHT OUTER JOIN [TABLE] test ON test.KEY = item.KEY
WHERE item.KEY IN (?, ?, ..., ?);

4. 해결 방법 – 임시 테이블 활용

IN 절을 나누기보다 임시 테이블(Global Temporary Table)을 사용하는 방식이 대량 처리 시 성능과 유지보수 측면에서 더 적합합니다.

CREATE GLOBAL TEMPORARY TABLE TEMP_IDS (
  ID NUMBER PRIMARY KEY
) ON COMMIT DELETE ROWS;

INSERT INTO TEMP_IDS (ID) VALUES (...);

SELECT item.*
FROM [TABLE]_ITEM item
JOIN TEMP_IDS temp ON item.KEY = temp.ID;

5. Java에서 임시 테이블 사용하는 예시

public void runWithTempTable(List<Long> ids) {
    jdbcTemplate.batchUpdate("INSERT INTO TEMP_IDS (ID) VALUES (?)",
        ids, 1000, (ps, id) -> ps.setLong(1, id));

    List<Result> results = jdbcTemplate.query(
        "SELECT ... FROM MAIN_TABLE m JOIN TEMP_IDS t ON m.ID = t.ID",
        new BeanPropertyRowMapper<>(Result.class));
}

6. 분할 처리와 비교

항목IN 절 분할임시 테이블
구현 난이도낮음중간
성능 (5천 건 이상)낮음높음
실행 계획 최적화불리함유리함
쿼리 가독성낮음높음
실무 적합성소량 요청대량 처리

7. 정리

  • Oracle IN 절은 1000개를 초과하면 ORA-01795 에러가 발생합니다.
  • 대량의 ID를 조건으로 사용할 경우, 임시 테이블을 통한 JOIN 방식이 권장됩니다.
  • Java에서는 batch insert와 JOIN 쿼리를 조합하여 안정적으로 처리할 수 있습니다.
반응형

댓글