2026년 08월 17일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-02296 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-02296 cannot enable – null values found 는?
ORA-02296 에러는 기존 테이블에 NOT NULL 제약 조건 또는 CHECK 제약 조건을 활성화(ENABLE)하려 할 때, 해당 컬럼에 이미 NULL 값이 존재하여 제약 조건을 적용할 수 없는 경우 발생합니다. 즉, 데이터가 이미 쌓여 있는 상태에서 뒤늦게 무결성 규칙을 강제하려 할 때 Oracle이 기존 데이터를 검사하고 위반 데이터를 발견하면 이 에러를 던집니다. 운영 중인 시스템에서 DDL 변경 작업을 수행하거나, 데이터 마이그레이션 이후 제약 조건을 재활성화하는 과정에서 매우 자주 마주치는 에러입니다.
주요 발생 원인
1. 기존 테이블 컬럼에 NOT NULL 제약 조건 추가 시 NULL 데이터 존재
가장 흔한 원인으로, 운영 중인 테이블에 특정 컬럼을 NOT NULL로 변경하거나 새로운 NOT NULL 컬럼을 추가할 때 발생합니다. 이미 INSERT된 로우 중에 해당 컬럼 값이 NULL인 경우, Oracle은 제약 조건 활성화를 거부하고 ORA-02296을 반환합니다. 예를 들어 수천만 건의 주문 데이터에서 배송지 주소 컬럼이 일부 비어 있다면, 이 컬럼에 NOT NULL을 걸 수 없습니다.
2. DISABLE 상태의 제약 조건을 ENABLE로 전환 시 기존 데이터 위반
제약 조건을 DISABLE 상태로 두고 대량 데이터를 적재(배치 작업, 마이그레이션)한 후 다시 ENABLE로 전환하려 할 때 이 에러가 발생합니다. DISABLE 상태에서는 무결성 검사가 이루어지지 않기 때문에, NULL을 포함한 부적합 데이터가 테이블에 존재할 수 있습니다. 이를 모르고 단순히 ALTER TABLE ... ENABLE CONSTRAINT를 실행하면 Oracle이 전체 데이터를 스캔하면서 위반 로우를 발견하고 에러를 발생시킵니다.
3. 데이터 마이그레이션 또는 외부 시스템 연동 후 제약 조건 재활성화
레거시 시스템에서 데이터를 이관하거나 외부 파일(CSV, Excel 등)로부터 데이터를 대량으로 로드한 후, 원래 있던 제약 조건을 다시 활성화하는 시나리오에서 자주 발생합니다. 소스 시스템과 타깃 시스템 간의 데이터 품질 차이, NULL 허용 정책의 차이로 인해 마이그레이션된 데이터에 NULL이 포함되어 있을 수 있습니다. 이 경우 단순한 ENABLE 명령만으로는 해결이 되지 않으며, 반드시 데이터 정제 작업이 선행되어야 합니다.
해결 방법
방법 1: NULL 값 데이터 확인 및 업데이트
먼저 어떤 컬럼에, 몇 건의 NULL이 존재하는지 파악합니다.
-- NULL 값이 있는 로우 수 확인
SELECT COUNT(*)
FROM employees
WHERE department_id IS NULL;
-- NULL 값이 있는 실제 데이터 조회
SELECT employee_id, first_name, last_name, department_id
FROM employees
WHERE department_id IS NULL;
NULL 값을 적절한 기본값으로 업데이트한 후 제약 조건을 활성화합니다.
-- NULL 값을 기본값으로 업데이트
UPDATE employees
SET department_id = 0 -- 미지정 부서를 의미하는 기본값
WHERE department_id IS NULL;
COMMIT;
-- 제약 조건 활성화
ALTER TABLE employees
MODIFY department_id NOT NULL;
방법 2: DISABLE 상태 제약 조건을 ENABLE로 전환
제약 조건 이름을 먼저 확인하고, NULL 데이터를 정리한 뒤 활성화합니다.
-- 현재 비활성화된 제약 조건 확인
SELECT constraint_name, constraint_type, status, table_name
FROM user_constraints
WHERE table_name = 'EMPLOYEES'
AND status = 'DISABLED';
-- NULL 데이터 정리 (예: 기본 부서 코드 99로 설정)
UPDATE employees
SET department_id = 99
WHERE department_id IS NULL;
COMMIT;
-- 제약 조건 활성화
ALTER TABLE employees ENABLE CONSTRAINT emp_dept_nn;
방법 3: EXCEPTIONS 테이블을 활용하여 위반 로우 식별
대용량 테이블에서 어떤 로우가 위반인지 정확히 파악하고 싶을 때는 EXCEPTIONS 테이블을 활용합니다.
-- EXCEPTIONS 테이블 생성 (Oracle 제공 스크립트 실행)
-- $ORACLE_HOME/rdbms/admin/utlexcpt.sql 실행
@$ORACLE_HOME/rdbms/admin/utlexcpt.sql
-- 위반 로우를 EXCEPTIONS 테이블에 기록하면서 ENABLE 시도
ALTER TABLE employees
ENABLE CONSTRAINT emp_dept_nn
EXCEPTIONS INTO exceptions;
-- 위반 로우 조회
SELECT e.row_id, emp.*
FROM exceptions e
JOIN employees emp ON emp.rowid = e.row_id
WHERE e.table_name = 'EMPLOYEES'
AND e.constraint = 'EMP_DEPT_NN';
-- 위반 데이터 수정 후 다시 ENABLE
UPDATE employees
SET department_id = 99
WHERE rowid IN (SELECT row_id FROM exceptions WHERE table_name = 'EMPLOYEES');
COMMIT;
ALTER TABLE employees ENABLE CONSTRAINT emp_dept_nn;
방법 4: 컬럼 추가 시 DEFAULT 값과 함께 NOT NULL 설정
신규 컬럼을 추가하면서 동시에 NOT NULL을 설정해야 할 때는 DEFAULT 값을 함께 지정합니다.
-- DEFAULT 값을 설정하면서 NOT NULL 컬럼 추가 (Oracle 11g 이상 권장)
ALTER TABLE employees
ADD (status_code VARCHAR2(10) DEFAULT 'ACTIVE' NOT NULL);
-- 이렇게 하면 기존 로우에 자동으로 DEFAULT 값이 채워지므로 ORA-02296 방지
예방 방법
1. 신규 컬럼 추가 시 반드시 DEFAULT 값 지정 후 NOT NULL 적용
NOT NULL 제약 조건을 가진 신규 컬럼을 기존 테이블에 추가할 때는 항상 DEFAULT 절을 함께 사용하는 것을 표준화하십시오. Oracle 11g R1부터는 DEFAULT 값이 있는 NOT NULL 컬럼 추가 시 데이터 딕셔너리에 기본값을 저장하고 실제 테이블 세그먼트를 업데이트하지 않는 최적화가 적용되어, 대용량 테이블에서도 매우 빠르게 처리됩니다. DDL 변경 전에 항상 사전 데이터 품질 점검 쿼리를 실행하는 습관을 팀 표준으로 정립하세요.
-- 개발 단계에서 사전 점검 쿼리 표준화 예시
SELECT column_name, COUNT(*) AS null_count
FROM (
SELECT 'DEPARTMENT_ID' AS column_name FROM employees WHERE department_id IS NULL
UNION ALL
SELECT 'MANAGER_ID' AS column_name FROM employees WHERE manager_id IS NULL
)
GROUP BY column_name
HAVING COUNT(*) > 0;
2. 배치 적재 또는 마이그레이션 시 제약 조건 관리 절차 수립
대량 데이터 작업 전에 제약 조건을 DISABLE하고 작업 후 ENABLE하는 경우, 반드시 ENABLE 전에 데이터 정합성 검증 스크립트를 자동화하여 실행하도록 운영 절차를 표준화하세요. CI/CD 파이프라인이나 배치 JOB에 데이터 검증 단계를 필수로 포함시키고, 위반 데이터가 존재할 경우 작업을 중단하고 담당자에게 알림이 가도록 설계하는 것이 Best Practice입니다.
관련 에러
- ORA-02290: CHECK 제약 조건 위반 (check constraint violated). NOT NULL이 아닌 CHECK 조건에 맞지 않는 데이터가 INSERT/UPDATE될 때 발생합니다.
- ORA-02291: 부모 키가 존재하지 않아 무결성 제약 조건 위반 (integrity constraint violated – parent key not found). 외래 키 제약 조건 활성화 시 참조되는 부모 테이블에 해당 키가 없을 때 발생합니다.
- ORA-02292: 자식 레코드가 존재하여 무결성 제약 조건 위반 (integrity constraint violated – child record found). 부모 테이블의 레코드를 삭제하려 할 때 자식 테이블에 참조 데이터가 존재하면 발생합니다.
- ORA-01400: NULL을 NOT NULL 컬럼에 삽입하려 할 때 발생하며, ORA-02296과 반대 방향의 에러입니다 (INSERT/UPDATE 시점에 발생).
- ORA-02293: 제약 조건 활성화 시 UNIQUE 또는 PRIMARY KEY 위반이 발견될 때 발생하는 에러로, ORA-02296과 동일한 ENABLE 작업 중에 마주칠 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.