Oracle ORA-02149 오류 원인과 해결 방법 완벽 가이드

ORA-02149
2026년 08월 11일 | DBMS Error 가이드

이 글에서 다루는 내용

ORA-02149 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

ORA-02149 Specified partition does not exist 는?

ORA-02149 에러는 Oracle 파티션 테이블 또는 파티션 인덱스에 접근할 때, 존재하지 않는 파티션 이름이나 파티션 번호를 지정했을 경우 발생하는 에러입니다. 주로 ALTER TABLE ... DROP PARTITION, SELECT ... PARTITION (partition_name), ALTER TABLE ... TRUNCATE PARTITION 등의 구문에서 파티션 이름을 잘못 입력하거나, 이미 삭제된 파티션을 참조할 때 발생합니다. 운영 환경에서 파티션 관리 작업 중 오탈자나 대소문자 불일치, 혹은 자동화 스크립트의 파티션 이름 매핑 오류로 인해 빈번하게 발생하며, 자칫하면 중요한 배치 작업이나 유지보수 작업을 중단시키는 원인이 됩니다.


주요 발생 원인

1. 파티션 이름 오탈자 또는 대소문자 불일치

Oracle에서 파티션 이름은 기본적으로 대문자로 저장됩니다. 파티션을 생성할 때 명시적으로 소문자나 혼합 형태로 지정하지 않은 경우, 데이터 딕셔너리에는 대문자로 등록됩니다. 예를 들어 PARTITION (sales_q1_2024) 로 소문자 입력 시, 실제로 SALES_Q1_2024 로 저장된 파티션과 불일치하여 에러가 발생할 수 있습니다. 특히 동적 SQL이나 쉘 스크립트로 파티션 이름을 자동 생성하는 경우, 이 대소문자 문제가 자주 간과됩니다.

2. 파티션이 이미 삭제되었거나 Merge/Split 작업으로 재구성된 경우

운영 중 파티션 유지보수 작업(DROP, MERGE, SPLIT, EXCHANGE)을 수행하면 기존 파티션 이름이 사라지거나 변경될 수 있습니다. 특히 오래된 데이터를 주기적으로 DROP하는 자동화 스크립트가 있는 환경에서, 해당 파티션을 참조하는 다른 프로세스나 쿼리가 이미 삭제된 파티션에 접근하려 할 때 ORA-02149가 발생합니다. 배치 스케줄러가 파티션 이름을 하드코딩하고 있다면 이 상황이 특히 위험합니다.

3. 파티션 테이블이 아닌 일반 테이블에 파티션 구문 적용

파티션 테이블이 아닌 일반 힙 테이블(non-partitioned table)에 PARTITION 절을 사용하는 쿼리나 DDL을 실행할 경우에도 유사한 에러가 발생할 수 있습니다. 개발 환경과 운영 환경의 테이블 구조가 다를 때, 또는 파티션 테이블에서 일반 테이블로 마이그레이션 후 기존 쿼리를 그대로 사용할 때 이 문제가 나타납니다. 이 경우는 ORA-02149보다 ORA-14501이 먼저 발생하는 경우도 있지만, 상황에 따라 혼용될 수 있습니다.


해결 방법

1단계: 현재 존재하는 파티션 목록 확인

에러가 발생하면 먼저 해당 테이블의 실제 파티션 이름을 확인해야 합니다.

-- 특정 테이블의 파티션 목록 조회
SELECT partition_name,
       partition_position,
       high_value,
       num_rows,
       last_analyzed
FROM   user_tab_partitions
WHERE  table_name = 'SALES'  -- 대문자로 입력
ORDER  BY partition_position;

-- DBA 권한이 있는 경우 다른 스키마의 파티션도 조회 가능
SELECT table_owner,
       table_name,
       partition_name,
       high_value
FROM   dba_tab_partitions
WHERE  table_name  = 'SALES'
AND    table_owner = 'SCOTT'
ORDER  BY partition_position;

2단계: 올바른 파티션 이름으로 구문 수정

파티션 이름을 확인한 후, 정확한 이름으로 구문을 수정하여 재실행합니다.

-- 잘못된 예시 (에러 발생)
SELECT *
FROM   sales PARTITION (sales_q1_2024);  -- 소문자로 인해 에러 가능

-- 올바른 예시
SELECT *
FROM   sales PARTITION (SALES_Q1_2024);  -- 정확한 파티션 이름 사용

-- 파티션 TRUNCATE 예시
ALTER TABLE sales TRUNCATE PARTITION SALES_Q1_2024;

-- 파티션 DROP 예시
ALTER TABLE sales DROP PARTITION SALES_Q1_2024;

3단계: 동적 SQL로 파티션 이름을 안전하게 처리

파티션 이름을 동적으로 생성하는 경우, 데이터 딕셔너리에서 실제 이름을 조회하여 사용하는 것이 안전합니다.

-- 동적 SQL로 파티션 관리하는 안전한 프로시저 예시
DECLARE
  v_partition_name VARCHAR2(128);
  v_sql            VARCHAR2(500);
  v_target_date    DATE := ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -3); -- 3개월 전
BEGIN
  -- 데이터 딕셔너리에서 실제 파티션 이름 조회
  BEGIN
    SELECT partition_name
    INTO   v_partition_name
    FROM   user_tab_partitions
    WHERE  table_name = 'SALES'
      AND  high_value <= TO_CHAR(v_target_date, 'SYYYY-MM-DD HH24:MI:SS') -- 예시
    FETCH FIRST 1 ROW ONLY;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('해당 파티션이 존재하지 않습니다. 작업을 건너뜁니다.');
      RETURN;
  END;

  -- 조회된 파티션 이름으로 동적 SQL 생성
  v_sql := 'ALTER TABLE SALES DROP PARTITION ' || v_partition_name;
  DBMS_OUTPUT.PUT_LINE('실행 SQL: ' || v_sql);

  -- 실제 실행 (운영 적용 전 반드시 테스트)
  EXECUTE IMMEDIATE v_sql;

  DBMS_OUTPUT.PUT_LINE('파티션 ' || v_partition_name || ' 삭제 완료');
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('에러 발생: ' || SQLERRM);
    RAISE;
END;
/

4단계: 파티션 인덱스 관련 에러 해결

파티션 인덱스에서 발생하는 경우에도 동일하게 딕셔너리를 먼저 조회합니다.

-- 인덱스 파티션 목록 확인
SELECT index_name,
       partition_name,
       status,
       high_value
FROM   user_ind_partitions
WHERE  index_name = 'IDX_SALES_DATE'
ORDER  BY partition_position;

-- 인덱스 파티션 재빌드 예시
ALTER INDEX idx_sales_date REBUILD PARTITION SALES_Q1_2024;

예방 방법

1. 파티션 관련 DDL/DML 실행 전 존재 여부 사전 검증 루틴 적용

모든 파티션 유지보수 스크립트에는 반드시 파티션 존재 여부를 사전에 확인하는 검증 로직을 포함시켜야 합니다. 아래와 같이 파티션 존재 여부를 체크하는 공통 함수를 만들어두고 재사용하는 것이 Best Practice입니다.

-- 파티션 존재 여부 확인 함수
CREATE OR REPLACE FUNCTION fn_partition_exists (
  p_table_name     IN VARCHAR2,
  p_partition_name IN VARCHAR2,
  p_owner          IN VARCHAR2 DEFAULT USER
) RETURN BOOLEAN IS
  v_cnt NUMBER;
BEGIN
  SELECT COUNT(*)
  INTO   v_cnt
  FROM   dba_tab_partitions
  WHERE  table_owner     = UPPER(p_owner)
    AND  table_name      = UPPER(p_table_name)
    AND  partition_name  = UPPER(p_partition_name);

  RETURN (v_cnt > 0);
END fn_partition_exists;
/

-- 사용 예시
BEGIN
  IF fn_partition_exists('SALES', 'SALES_Q1_2024') THEN
    EXECUTE IMMEDIATE 'ALTER TABLE SALES DROP PARTITION SALES_Q1_2024';
    DBMS_OUTPUT.PUT_LINE('파티션 삭제 완료');
  ELSE
    DBMS_OUTPUT.PUT_LINE('파티션이 존재하지 않습니다. 작업 생략.');
  END IF;
END;
/

2. 파티션 네이밍 컨벤션 표준화 및 문서화

파티션 이름 규칙을 사전에 표준화하고, 신규 파티션 추가 시 반드시 해당 규칙을 따르도록 DBA 가이드라인을 수립해야 합니다. 예를 들어 TB명_YYYYMM 형태로 파티션 이름을 통일하면, 스크립트에서 파티션 이름을 동적으로 예측하기 용이해집니다. 또한 파티션 구조 변경(MERGE, SPLIT, DROP) 이력을 Wiki나 형상관리 시스템에 반드시 기록하여, 관련 스크립트 및 쿼리를 즉시 업데이트할 수 있도록 합니다.


관련 에러

  • ORA-02149: 현재 에러. 지정한 파티션이 존재하지 않음.
  • ORA-14501: OBJECT IS NOT PARTITIONED – 파티션 구문을 비파티션 테이블에 적용했을 때 발생.
  • ORA-14758: LAST PARTITION IN THE RANGE SECTION CANNOT BE DROPPED – Range 파티션의 마지막 파티션을 DROP하려 할 때 발생.
  • ORA-14312: INVALID TIME LIMIT SPECIFIED – 파티션 작업 시 제한 시간 지정 오류.
  • ORA-02148: SPECIFIED PARTITION NAME IS DUPLICATE – 동일 이름의 파티션이 이미 존재할 때 발생하며, ORA-02149와 함께 파티션 이름 관리 실수에서 쌍으로 발생하는 경우가 많음.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기