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

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

이 글에서 다루는 내용

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

ORA-02291 integrity constraint violated – parent key not found 는?

ORA-02291 에러는 외래 키(Foreign Key) 제약 조건을 위반했을 때 발생하는 Oracle 데이터베이스의 무결성 오류입니다. 자식 테이블(Child Table)에 데이터를 INSERT하거나 UPDATE할 때, 참조하는 부모 테이블(Parent Table)에 해당 키 값이 존재하지 않을 경우 이 에러가 발생합니다. 쉽게 말해, 부모가 없는 자식 레코드를 만들려고 시도했을 때 Oracle이 데이터 무결성을 지키기 위해 해당 작업을 차단하는 것입니다.


주요 발생 원인

1. 부모 테이블에 존재하지 않는 키 값으로 INSERT/UPDATE 시도

가장 흔한 원인으로, 자식 테이블에 데이터를 삽입할 때 참조하는 부모 키 값이 부모 테이블에 아직 없는 경우입니다. 예를 들어, ORDERS 테이블에 주문을 등록할 때 CUSTOMERS 테이블에 존재하지 않는 CUSTOMER_ID를 사용하면 이 에러가 발생합니다. 실무에서는 배치 작업이나 데이터 마이그레이션 시 로딩 순서를 잘못 설정했을 때 자주 목격됩니다.

2. 트랜잭션 순서 오류 (부모 INSERT 전 자식 INSERT)

하나의 트랜잭션 또는 배치 프로세스 내에서 자식 테이블 데이터를 부모 테이블 데이터보다 먼저 삽입하려고 할 때 발생합니다. 특히 ETL(Extract, Transform, Load) 작업이나 대용량 데이터 적재 시, 참조 무결성을 고려하지 않고 단순히 테이블 알파벳 순서나 편의대로 로딩 순서를 정했을 때 이 문제가 자주 나타납니다. COMMIT 타이밍 문제로 인해 다른 세션에서 아직 부모 데이터가 보이지 않을 때도 동일 증상이 나타날 수 있습니다.

3. 잘못된 데이터 또는 타입 불일치

참조하려는 키 값이 실제로 부모 테이블에 있더라도, 데이터 타입 불일치, 선행/후행 공백, 또는 대소문자 차이로 인해 매칭이 실패하여 에러가 발생하기도 합니다. 예를 들어 부모 테이블의 키가 VARCHAR2 타입으로 '001'이 저장되어 있는데, 자식 테이블에서 숫자 1을 삽입하거나 ' 001'(공백 포함)을 넣으면 동일한 에러가 발생할 수 있습니다. 데이터 품질 문제가 복합적으로 작용하는 경우이므로 주의가 필요합니다.


해결 방법

원인 1 해결: 부모 데이터 먼저 확인 및 삽입

자식 테이블에 INSERT하기 전, 참조할 부모 키 값이 실제로 존재하는지 먼저 확인합니다.

-- 부모 테이블에 해당 키가 존재하는지 확인
SELECT customer_id
FROM customers
WHERE customer_id = 999;

-- 존재하지 않는다면 부모 데이터 먼저 삽입
INSERT INTO customers (customer_id, customer_name, created_date)
VALUES (999, '홍길동', SYSDATE);

COMMIT;

-- 그 후 자식 테이블에 데이터 삽입
INSERT INTO orders (order_id, customer_id, order_date, total_amount)
VALUES (10001, 999, SYSDATE, 50000);

COMMIT;

원인 2 해결: 트랜잭션 순서 재정렬

배치 또는 마이그레이션 스크립트에서 반드시 부모 테이블 → 자식 테이블 순서로 데이터를 로딩합니다.

-- 잘못된 순서 (에러 발생)
-- INSERT INTO orders ... (부모 없이 자식 먼저 삽입 시도)

-- 올바른 순서
-- STEP 1: 부모 테이블 먼저 로딩
INSERT INTO departments (dept_id, dept_name)
VALUES (10, '개발팀');

INSERT INTO departments (dept_id, dept_name)
VALUES (20, '영업팀');

COMMIT;

-- STEP 2: 자식 테이블 로딩
INSERT INTO employees (emp_id, emp_name, dept_id, hire_date)
VALUES (1001, '김철수', 10, SYSDATE);

INSERT INTO employees (emp_id, emp_name, dept_id, hire_date)
VALUES (1002, '이영희', 20, SYSDATE);

COMMIT;

대용량 데이터 마이그레이션 시 제약 조건을 임시로 비활성화하는 방법도 활용할 수 있습니다. 단, 반드시 데이터 정합성을 보장한 후 재활성화해야 합니다.

-- 제약 조건 임시 비활성화 (마이그레이션 시작 전)
ALTER TABLE employees
DISABLE CONSTRAINT fk_emp_dept;

-- 데이터 로딩 (순서 무관하게 가능)
INSERT INTO employees (emp_id, emp_name, dept_id, hire_date)
VALUES (2001, '박민준', 30, SYSDATE);

COMMIT;

-- 부모 테이블 데이터 보완
INSERT INTO departments (dept_id, dept_name)
VALUES (30, 'QA팀');

COMMIT;

-- 제약 조건 재활성화 (데이터 정합성 검증 포함)
ALTER TABLE employees
ENABLE CONSTRAINT fk_emp_dept;
-- 만약 정합성 위반 데이터가 있으면 이 시점에 ORA-02298 발생

원인 3 해결: 데이터 타입 및 값 정합성 확인

부모 테이블의 실제 키 값과 자식 테이블에서 참조하려는 값을 비교하여 불일치를 찾아냅니다.

-- 자식 테이블에 삽입 시도 전 매핑 확인
-- TRIM과 TO_CHAR 등을 활용하여 타입/공백 불일치 탐지
SELECT c.customer_id, c.customer_name
FROM customers c
WHERE c.customer_id = TO_NUMBER('0999');  -- 타입 변환 주의

-- 부모-자식 간 불일치 데이터 탐지 쿼리 (마이그레이션 검증용)
SELECT o.order_id, o.customer_id
FROM orders_staging o
WHERE NOT EXISTS (
    SELECT 1
    FROM customers c
    WHERE c.customer_id = o.customer_id
)
ORDER BY o.order_id;

-- 공백 문제 확인
SELECT '*' || customer_code || '*' AS check_value
FROM customers
WHERE customer_id = 100;
-- 결과에 공백이 포함되어 있는지 확인 후 TRIM 처리

예방 방법

1. 데이터 로딩 전 참조 무결성 사전 검증 스크립트 운영

배치 작업이나 데이터 마이그레이션을 수행하기 전, 반드시 소스 데이터를 대상으로 부모-자식 관계의 정합성을 사전에 검증하는 스크립트를 자동화하여 실행합니다. 이를 통해 실제 운영 DB에 잘못된 데이터가 유입되기 전에 오류를 발견할 수 있으며, 운영 장애를 미연에 방지할 수 있습니다.

-- 마이그레이션 전 사전 검증 예시
SELECT COUNT(*) AS orphan_count
FROM new_orders_data n
WHERE NOT EXISTS (
    SELECT 1 FROM customers c
    WHERE c.customer_id = n.customer_id
);
-- 결과가 0이어야 안전하게 로딩 가능

2. 애플리케이션 레이어에서 입력 값 유효성 검사 강화

데이터베이스의 제약 조건에만 의존하지 않고, 애플리케이션(백엔드 서버, API 레이어)에서도 외래 키 참조 값의 유효성을 사전에 검사하는 로직을 구현합니다. DB 에러가 최종 사용자에게 노출되기 전에 애플리케이션 레벨에서 먼저 걸러내면 사용자 경험도 개선되고 불필요한 DB 에러 로그도 줄일 수 있습니다.


관련 에러

  • ORA-02292: integrity constraint violated - child record found — ORA-02291의 반대 상황으로, 부모 레코드를 삭제하려 할 때 자식 레코드가 존재하여 삭제가 차단될 때 발생합니다.
  • ORA-02298: cannot validate - parent keys not found — 비활성화된 외래 키 제약 조건을 ENABLE 할 때, 기존 데이터 중 부모 키가 없는 레코드가 있으면 발생합니다.
  • ORA-00001: unique constraint violated — 기본 키 또는 유니크 제약 조건 위반으로, ORA-02291과 함께 데이터 무결성 관련 에러로 자주 함께 다루어집니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기