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 error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.