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

ORA-02290
2026년 08월 16일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-02290 check constraint violated 는?

ORA-02290 에러는 테이블에 정의된 CHECK 제약 조건을 위반하는 데이터를 INSERT 또는 UPDATE 하려고 할 때 발생합니다. Oracle 데이터베이스는 데이터 무결성을 보장하기 위해 CHECK 제약 조건에 정의된 조건식을 위반하는 값의 입력을 거부하며, 해당 DML 문장을 롤백합니다. 예를 들어, 나이(AGE) 컬럼에 0보다 크고 150보다 작아야 한다는 제약이 걸려 있는데 -1이나 200 같은 값을 입력하면 이 에러가 발생합니다.


주요 발생 원인

  • 잘못된 값 범위 입력

가장 흔한 원인으로, CHECK 제약 조건에서 허용하는 값의 범위를 벗어난 데이터를 삽입하거나 수정할 때 발생합니다. 예를 들어 SALARY > 0 조건이 걸려 있는 컬럼에 음수 값을 넣거나, STATUS IN ('ACTIVE', 'INACTIVE') 조건이 있는 컬럼에 ‘PENDING’ 같은 허용되지 않는 문자열을 입력하는 경우입니다. 개발 초기에는 잘 동작하다가 요구사항 변경으로 새로운 값이 추가될 때 자주 발생합니다.

  • 애플리케이션과 데이터베이스 간 제약 조건 불일치

애플리케이션 레이어(Java, Python 등)에서는 유효성 검사를 통과했더라도, 데이터베이스에 정의된 CHECK 제약 조건이 더 엄격한 경우 이 에러가 발생합니다. 특히 레거시 시스템을 유지보수하거나, 여러 팀이 협업하는 환경에서 DB 스키마 변경 사항이 애플리케이션에 반영되지 않았을 때 빈번하게 발생합니다. 데이터 마이그레이션 작업 시 기존 시스템의 데이터를 그대로 옮기는 과정에서도 이 문제가 생길 수 있습니다.

  • 배치 작업 또는 직접 DML 실행 시 데이터 품질 문제

야간 배치 작업이나 데이터 마이그레이션 스크립트 실행 시 대량의 데이터를 처리하는 과정에서 소수의 불량 데이터가 포함되어 에러가 발생하는 경우입니다. ETL 작업에서 외부 소스 시스템의 데이터가 타겟 Oracle DB의 CHECK 제약을 만족하지 못하는 경우가 대표적입니다. 이 경우 단 한 건의 위반 데이터로 인해 전체 배치가 실패할 수 있으므로 사전 데이터 검증이 매우 중요합니다.


해결 방법

1단계: 위반된 제약 조건 확인

먼저 어떤 CHECK 제약 조건이 위반되었는지 확인합니다.

-- 에러 메시지에서 제약 조건 이름 확인 후 상세 조회
SELECT constraint_name,
       constraint_type,
       search_condition,
       status,
       table_name
FROM   user_constraints
WHERE  constraint_type = 'C'
  AND  table_name = 'EMPLOYEES'; -- 대상 테이블명

-- 특정 제약 조건 이름으로 조회
SELECT constraint_name,
       search_condition
FROM   user_constraints
WHERE  constraint_name = 'CHK_EMP_SALARY'; -- 에러에서 확인된 제약 조건명

2단계: 위반 데이터 사전 조회

DML 실행 전 위반 가능한 데이터를 미리 찾아냅니다.

-- 예: SALARY 컬럼에 CHECK (SALARY > 0) 제약이 걸려 있는 경우
-- 위반 데이터 미리 확인
SELECT employee_id, salary
FROM   employees
WHERE  salary <= 0;

-- STATUS 컬럼에 CHECK (STATUS IN ('ACTIVE','INACTIVE')) 제약이 있는 경우
SELECT employee_id, status
FROM   employees_staging
WHERE  status NOT IN ('ACTIVE', 'INACTIVE');

3단계: 데이터 수정 또는 제약 조건 변경

방법 A – 데이터를 올바른 값으로 수정

-- 잘못된 급여 값을 최솟값으로 보정
UPDATE employees
SET    salary = 1000
WHERE  salary <= 0;

COMMIT;

-- 허용되지 않는 STATUS 값을 기본값으로 변경
UPDATE employees_staging
SET    status = 'INACTIVE'
WHERE  status NOT IN ('ACTIVE', 'INACTIVE');

COMMIT;

방법 B – 비즈니스 요건 변경으로 제약 조건을 수정해야 하는 경우

-- 기존 CHECK 제약 조건 비활성화
ALTER TABLE employees
DISABLE CONSTRAINT chk_emp_salary;

-- 제약 조건 삭제 후 새로운 조건으로 재생성
ALTER TABLE employees
DROP CONSTRAINT chk_emp_salary;

ALTER TABLE employees
ADD CONSTRAINT chk_emp_salary CHECK (salary >= 0); -- 0도 허용하도록 변경

-- 제약 조건 활성화 (기존 데이터 검증 포함)
ALTER TABLE employees
ENABLE CONSTRAINT chk_emp_salary;

방법 C – 대량 마이그레이션 시 임시 비활성화 후 검증

-- 제약 조건 임시 비활성화 (데이터 로드용)
ALTER TABLE employees
DISABLE CONSTRAINT chk_emp_status NOVALIDATE;

-- 데이터 로드 수행
INSERT INTO employees (employee_id, name, status)
SELECT employee_id, name, NVL(status, 'INACTIVE')
FROM   employees_source;

COMMIT;

-- 데이터 정제 후 제약 조건 재활성화
ALTER TABLE employees
ENABLE VALIDATE CONSTRAINT chk_emp_status;

4단계: 신규 CHECK 제약 조건 생성 예시

-- 테이블 생성 시 CHECK 제약 조건 포함
CREATE TABLE orders (
    order_id     NUMBER        PRIMARY KEY,
    order_date   DATE          NOT NULL,
    amount       NUMBER(15,2)  CONSTRAINT chk_order_amount   CHECK (amount > 0),
    status       VARCHAR2(20)  CONSTRAINT chk_order_status   CHECK (status IN ('PENDING','CONFIRMED','SHIPPED','CANCELLED')),
    discount_pct NUMBER(5,2)   CONSTRAINT chk_order_discount CHECK (discount_pct BETWEEN 0 AND 100)
);

-- 기존 테이블에 CHECK 제약 조건 추가
ALTER TABLE orders
ADD CONSTRAINT chk_order_date
CHECK (order_date >= DATE '2000-01-01');

예방 방법

  • DML 실행 전 사전 유효성 검사 루틴 도입

배치 작업이나 마이그레이션 전에 반드시 데이터 품질 검증 쿼리를 선행 실행하는 절차를 표준화하십시오. 아래와 같이 사전 검증 프로시저를 만들어두면 CHECK 제약 위반 건수를 미리 파악할 수 있어 본 작업 실패를 예방할 수 있습니다.

“`sql

— 사전 검증 프로시저 예시

CREATE OR REPLACE PROCEDURE validate_employee_data AS

v_invalid_count NUMBER;

BEGIN

— 급여 범위 체크

SELECT COUNT(*)

INTO v_invalid_count

FROM employees_staging

WHERE salary <= 0 OR salary > 99999999;

IF v_invalid_count > 0 THEN

RAISE_APPLICATION_ERROR(-20001,

‘급여 범위 위반 데이터 ‘ || v_invalid_count || ‘건 발견. 마이그레이션 중단.’);

END IF;

— 상태값 체크

SELECT COUNT(*)

INTO v_invalid_count

FROM employees_staging

WHERE status NOT IN (‘ACTIVE’, ‘INACTIVE’);

IF v_invalid_count > 0 THEN

RAISE_APPLICATION_ERROR(-20002,

‘허용되지 않는 STATUS 값 ‘ || v_invalid_count || ‘건 발견. 마이그레이션 중단.’);

END IF;

DBMS_OUTPUT.PUT_LINE(‘사전 검증 완료: 모든 데이터가 유효합니다.’);

END validate_employee_data;

/

“`

  • 데이터 사전(Data Dictionary)을 통한 제약 조건 문서화 및 주기적 리뷰

프로젝트 진행 중 CHECK 제약 조건이 변경될 때마다 애플리케이션 팀에 즉시 공유하는 프로세스를 만들고, 아래 쿼리를 이용해 전체 제약 조건 현황을 주기적으로 문서화하십시오. 이를 통해 개발팀과 DBA 간의 인식 차이를 줄이고, 신규 개발 시 제약 조건을 사전에 인지할 수 있습니다.

“`sql

— 전체 CHECK 제약 조건 현황 조회 (문서화용)

SELECT t.table_name,

c.constraint_name,

c.search_condition,

c.status,

c.validated

FROM user_tables t

JOIN user_constraints c ON t.table_name = c.table_name

WHERE c.constraint_type = ‘C’

ORDER BY t.table_name, c.constraint_name;

“`


관련 에러

  • ORA-02291: 부모 키가 없어 발생하는 외래 키(FK) 무결성 제약 위반 에러로, CHECK 제약이 아닌 참조 무결성 문제입니다.
  • ORA-02292: 자식 레코드가 존재하는 부모 레코드를 삭제하거나 업데이트할 때 발생하는 참조 무결성 에러입니다.
  • ORA-01400: NOT NULL 제약 조건 위반으로, NULL이 허용되지 않는 컬럼에 NULL 값을 삽입할 때 발생합니다.
  • ORA-00001: UNIQUE 제약 조건 위반으로, 중복된 값을 고유 키 컬럼에 삽입할 때 발생합니다.
  • ORA-02293: CHECK 제약 조건을 ENABLE 하려 할 때 기존 데이터 중 제약을 위반하는 데이터가 있을 때 발생합니다. 기존 테이블에 새 CHECK 제약을 추가할 때 자주 마주칩니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기