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

ORA-14099
2026년 09월 23일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-14099 all rows in table do not qualify for specified partition 는?

ORA-14099 에러는 파티션 테이블에 대해 ALTER TABLE ... EXCHANGE PARTITION 작업을 수행할 때, 일반 테이블의 모든 행이 지정된 파티션의 파티션 키 범위 조건을 만족하지 않을 때 발생합니다. 즉, 파티션 교환(Exchange) 대상 테이블에 해당 파티션의 범위를 벗어나는 데이터가 존재하는 경우 Oracle이 이 에러를 발생시킵니다. 이 에러는 주로 파티션 관리 작업, 대량 데이터 이행(Migration), 또는 파티션 유지보수 작업 중에 빈번하게 나타납니다.


주요 발생 원인

1. EXCHANGE PARTITION 시 데이터가 파티션 범위를 벗어난 경우

가장 흔한 원인으로, ALTER TABLE ... EXCHANGE PARTITION WITH TABLE 명령 실행 시 교환 대상 일반 테이블에 파티션 범위를 벗어나는 데이터가 포함된 경우입니다. 예를 들어 RANGE 파티션 기준이 SALE_DATE < '2024-01-01'인데, 일반 테이블에 2024-03-15 같은 날짜 데이터가 존재하면 이 에러가 발생합니다. Oracle은 기본적으로 INCLUDING ROWS 옵션을 사용하지 않으면 반드시 모든 행이 파티션 범위 안에 들어와야 한다는 규칙을 강제합니다.

2. 파티션 키 컬럼의 NULL 값 처리 문제

파티션 키 컬럼에 NULL 값이 포함된 경우에도 이 에러가 발생할 수 있습니다. RANGE 파티션에서 NULL 값은 MAXVALUE 파티션에 속하는데, 교환 대상 파티션이 MAXVALUE 파티션이 아닌 경우, NULL이 포함된 일반 테이블을 교환하려 하면 오류가 발생합니다. 이는 파티션 설계 시 NULL 처리 정책을 명확히 하지 않으면 실무에서 자주 마주치는 함정입니다.

3. LIST 또는 HASH 파티션에서의 값 불일치

LIST 파티션 테이블의 경우, 교환 대상 파티션에 정의된 값 목록에 포함되지 않는 데이터가 일반 테이블에 존재할 때 이 에러가 발생합니다. 예를 들어 REGION = 'ASIA' 파티션과 교환하려는 테이블에 REGION = 'EUROPE' 데이터가 있는 경우입니다. HASH 파티션에서도 해시 함수 결과가 일치하지 않는 행이 존재하면 동일한 문제가 발생합니다.


해결 방법

원인 1 해결: 데이터 범위 확인 후 정리

교환 전 반드시 일반 테이블의 데이터가 파티션 범위 내에 있는지 확인하고, 범위를 벗어난 데이터를 삭제하거나 이동시켜야 합니다.

-- 1단계: 파티션 범위 확인
SELECT PARTITION_NAME, HIGH_VALUE
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'SALES_PART'
ORDER BY PARTITION_POSITION;

-- 2단계: 교환 대상 일반 테이블에서 범위 벗어난 데이터 확인
-- (예: P_2023 파티션 범위가 2023-01-01 ~ 2023-12-31인 경우)
SELECT COUNT(*)
FROM SALES_TEMP
WHERE SALE_DATE NOT BETWEEN DATE '2023-01-01' AND DATE '2023-12-31';

-- 3단계: 범위 초과 데이터 별도 테이블로 이동
CREATE TABLE SALES_TEMP_OVERFLOW AS
SELECT * FROM SALES_TEMP
WHERE SALE_DATE NOT BETWEEN DATE '2023-01-01' AND DATE '2023-12-31';

-- 4단계: 범위 초과 데이터 삭제
DELETE FROM SALES_TEMP
WHERE SALE_DATE NOT BETWEEN DATE '2023-01-01' AND DATE '2023-12-31';
COMMIT;

-- 5단계: 파티션 교환 재시도
ALTER TABLE SALES_PART
EXCHANGE PARTITION P_2023
WITH TABLE SALES_TEMP
WITHOUT VALIDATION;

> ⚠️ WITHOUT VALIDATION 옵션은 데이터 검증을 생략하므로, 데이터 무결성을 사전에 직접 확인한 경우에만 사용하세요.


원인 2 해결: NULL 값 처리

-- NULL 값이 포함된 행 확인
SELECT COUNT(*)
FROM SALES_TEMP
WHERE SALE_DATE IS NULL;

-- NULL 값을 특정 기본값으로 업데이트하거나 삭제
UPDATE SALES_TEMP
SET SALE_DATE = DATE '2023-06-30'
WHERE SALE_DATE IS NULL;
COMMIT;

-- 또는 NULL 데이터 제거
DELETE FROM SALES_TEMP WHERE SALE_DATE IS NULL;
COMMIT;

-- NULL을 허용하는 MAXVALUE 파티션과 교환 시
ALTER TABLE SALES_PART
EXCHANGE PARTITION P_MAXVALUE
WITH TABLE SALES_NULL_TABLE;

원인 3 해결: LIST 파티션 값 불일치 해결

-- LIST 파티션 정의 확인
SELECT PARTITION_NAME, HIGH_VALUE
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'REGION_SALES'
AND PARTITION_NAME = 'P_ASIA';

-- 일반 테이블에서 허용되지 않는 LIST 값 확인
SELECT REGION, COUNT(*)
FROM REGION_TEMP
WHERE REGION NOT IN ('KOREA', 'JAPAN', 'CHINA')  -- P_ASIA 파티션의 LIST 값
GROUP BY REGION;

-- 허용되지 않는 데이터 처리
DELETE FROM REGION_TEMP
WHERE REGION NOT IN ('KOREA', 'JAPAN', 'CHINA');
COMMIT;

-- 이후 파티션 교환 수행
ALTER TABLE REGION_SALES
EXCHANGE PARTITION P_ASIA
WITH TABLE REGION_TEMP
WITH VALIDATION;

빠른 임시 해결: WITHOUT VALIDATION 사용

데이터 검증을 건너뛰고 빠르게 교환하고자 할 때 사용할 수 있으나, 반드시 사전에 데이터 무결성을 수동 확인해야 합니다.

-- WITHOUT VALIDATION으로 검증 우회 (주의: 데이터 무결성 보장 필요)
ALTER TABLE SALES_PART
EXCHANGE PARTITION P_2023
WITH TABLE SALES_TEMP
WITHOUT VALIDATION;

-- 교환 후 데이터 확인
SELECT COUNT(*) FROM SALES_PART PARTITION (P_2023);
SELECT COUNT(*) FROM SALES_TEMP;

예방 방법

1. EXCHANGE PARTITION 전 사전 검증 스크립트 의무화

파티션 교환 작업을 운영 환경에 적용하기 전, 반드시 데이터 범위 검증 스크립트를 표준 절차로 수립해야 합니다. 아래 스크립트를 템플릿으로 활용하여, 파티션 교환 전 QA 체크리스트에 포함시키는 것을 권장합니다.

-- 파티션 교환 사전 검증 공통 스크립트 (템플릿)
-- RANGE 파티션 검증 예시
DECLARE
    v_count NUMBER;
    v_low_val DATE := DATE '2023-01-01';
    v_high_val DATE := DATE '2024-01-01';
BEGIN
    SELECT COUNT(*) INTO v_count
    FROM SALES_TEMP
    WHERE SALE_DATE < v_low_val OR SALE_DATE >= v_high_val OR SALE_DATE IS NULL;

    IF v_count > 0 THEN
        DBMS_OUTPUT.PUT_LINE('검증 실패: ' || v_count || '건의 범위 초과 데이터 존재');
    ELSE
        DBMS_OUTPUT.PUT_LINE('검증 성공: 파티션 교환 가능');
    END IF;
END;
/

2. 파티션 테이블 설계 시 DEFAULT/MAXVALUE 파티션 반드시 포함

RANGE 또는 LIST 파티션 설계 시 예외 데이터를 수용할 수 있는 DEFAULT 또는 MAXVALUE 파티션을 반드시 포함하여 설계하세요. 이렇게 하면 예상치 못한 범위의 데이터가 유입되더라도 ORA-14099 발생 가능성을 크게 줄일 수 있습니다.

-- RANGE 파티션에 MAXVALUE 파티션 포함 설계 예시
CREATE TABLE SALES_PART (
    SALE_ID     NUMBER,
    SALE_DATE   DATE,
    AMOUNT      NUMBER
)
PARTITION BY RANGE (SALE_DATE) (
    PARTITION P_2022 VALUES LESS THAN (DATE '2023-01-01'),
    PARTITION P_2023 VALUES LESS THAN (DATE '2024-01-01'),
    PARTITION P_2024 VALUES LESS THAN (DATE '2025-01-01'),
    PARTITION P_MAX  VALUES LESS THAN (MAXVALUE)  -- 반드시 포함
);

관련 에러

  • ORA-14098: row does not fit any partition — 파티션 테이블에 INSERT 또는 UPDATE 시 해당 행이 어느 파티션에도 속하지 않을 때 발생하며, ORA-14099와 유사한 파티션 범위 문제를 다룹니다.
  • ORA-14019: partition bound element must be one of: string, datetime or interval literal, number, or MAXVALUE — 파티션 경계값 정의 오류로, 파티션 설계 단계에서 발생합니다.
  • ORA-14400: inserted partition key does not map to any partition — DML 작업 중 삽입하려는 데이터가 어느 파티션에도 매핑되지 않을 때 발생합니다. EXCHANGE PARTITION 이후 데이터 정합성 문제로 이어질 수 있어 함께 모니터링해야 합니다.
  • ORA-14501: object is not partitioned — 파티션이 아닌 테이블에 파티션 명령을 수행할 때 발생하는 에러로, EXCHANGE 대상 테이블 혼동 시 발생할 수 있습니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기