2026년 08월 17일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-02297 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-02297 cannot disable constraint – dependencies exist 는?
ORA-02297은 Oracle 데이터베이스에서 특정 제약 조건(Constraint)을 비활성화(DISABLE)하려고 할 때, 해당 제약 조건을 참조하는 다른 제약 조건이 존재하여 작업이 거부될 때 발생하는 에러입니다. 대표적인 사례는 부모 테이블의 PRIMARY KEY 또는 UNIQUE KEY를 비활성화하려는데, 자식 테이블에 해당 키를 참조하는 FOREIGN KEY 제약 조건이 살아있는 경우입니다. 즉, Oracle은 참조 무결성(Referential Integrity)을 보호하기 위해 의존성이 존재하는 한 상위 제약 조건의 비활성화를 허용하지 않습니다.
주요 발생 원인
1. 자식 테이블의 FOREIGN KEY가 부모 테이블의 PRIMARY KEY를 참조하고 있는 경우
가장 흔한 원인입니다. 부모 테이블의 PRIMARY KEY를 DISABLE하려고 할 때, 하나 이상의 자식 테이블이 해당 키를 FOREIGN KEY로 참조하고 있으면 Oracle은 즉시 ORA-02297을 반환합니다. 이는 데이터 무결성을 지키기 위한 Oracle의 기본 동작이며, 자식 테이블의 FK가 살아있는 상태에서는 절대 부모의 PK를 먼저 비활성화할 수 없습니다.
2. 여러 테이블에 걸친 복잡한 참조 체인(Reference Chain)이 형성된 경우
엔터프라이즈 환경에서는 A 테이블 → B 테이블 → C 테이블처럼 다단계 참조 체인이 형성되는 경우가 많습니다. 이때 중간 단계에 있는 B 테이블의 PK를 비활성화하려고 하면, C 테이블의 FK가 의존성으로 탐지되어 에러가 발생합니다. 참조 체인이 길수록 의존 관계를 파악하기 어려워지므로 사전에 전체 의존성 맵을 확인하는 것이 중요합니다.
3. UNIQUE KEY를 참조하는 FOREIGN KEY가 존재하는 경우
PRIMARY KEY만이 아니라 UNIQUE KEY도 FOREIGN KEY의 참조 대상이 될 수 있습니다. UNIQUE 제약 조건을 비활성화하려는 경우에도 해당 UNIQUE KEY를 참조하는 FK가 존재한다면 동일하게 ORA-02297이 발생합니다. 이는 많은 DBA들이 간과하기 쉬운 케이스로, UNIQUE KEY 변경 작업 전 반드시 의존성 확인 쿼리를 실행해야 합니다.
해결 방법
해결책 1: 의존 관계 사전 파악
제약 조건을 비활성화하기 전에 반드시 어떤 FK가 해당 PK/UK를 참조하고 있는지 확인합니다.
-- 특정 제약 조건을 참조하는 FK 목록 조회
SELECT a.owner AS fk_owner,
a.table_name AS fk_table,
a.constraint_name AS fk_constraint,
a.status AS fk_status,
b.owner AS ref_owner,
b.table_name AS ref_table,
b.constraint_name AS ref_constraint
FROM dba_constraints a
JOIN dba_constraints b
ON a.r_owner = b.owner
AND a.r_constraint_name = b.constraint_name
WHERE b.table_name = 'ORDERS' -- 부모 테이블명
AND b.constraint_name = 'PK_ORDERS' -- 비활성화 대상 제약 조건명
AND a.constraint_type = 'R'; -- R = FOREIGN KEY
해결책 2: 자식 테이블의 FK를 먼저 비활성화한 후 부모 PK 비활성화
올바른 순서는 자식 FK → 부모 PK 순으로 비활성화하는 것입니다.
-- Step 1: 자식 테이블의 FOREIGN KEY 먼저 비활성화
ALTER TABLE order_items
DISABLE CONSTRAINT fk_order_items_orders;
-- Step 2: 부모 테이블의 PRIMARY KEY 비활성화
ALTER TABLE orders
DISABLE CONSTRAINT pk_orders;
-- 작업 완료 후 역순으로 다시 활성화 (부모 PK 먼저)
ALTER TABLE orders
ENABLE CONSTRAINT pk_orders;
ALTER TABLE order_items
ENABLE CONSTRAINT fk_order_items_orders;
해결책 3: CASCADE 옵션을 활용한 일괄 비활성화
Oracle은 CASCADE 옵션을 통해 부모 제약 조건 비활성화 시 자식 FK도 함께 비활성화할 수 있습니다. 단, 이 옵션은 FK만 CASCADE 비활성화하며, 데이터에는 영향을 주지 않습니다.
-- CASCADE 옵션으로 참조 FK도 함께 비활성화
ALTER TABLE orders
DISABLE PRIMARY KEY CASCADE;
-- 현재 비활성화된 제약 조건 목록 확인
SELECT owner,
table_name,
constraint_name,
constraint_type,
status
FROM dba_constraints
WHERE table_name IN ('ORDERS', 'ORDER_ITEMS')
ORDER BY table_name, constraint_type;
해결책 4: 스크립트를 이용한 자동화된 비활성화/활성화 처리
여러 테이블에 걸친 복잡한 참조 체인이 있을 때 유용한 자동화 스크립트입니다.
-- 특정 테이블을 참조하는 모든 FK에 대한 DISABLE 스크립트 생성
SELECT 'ALTER TABLE ' || a.owner || '.' || a.table_name
|| ' DISABLE CONSTRAINT ' || a.constraint_name || ';' AS disable_sql
FROM dba_constraints a
JOIN dba_constraints b
ON a.r_owner = b.owner
AND a.r_constraint_name = b.constraint_name
WHERE b.table_name = 'ORDERS'
AND a.constraint_type = 'R'
ORDER BY a.table_name;
-- 동적 SQL을 이용한 PL/SQL 자동 처리 프로시저
BEGIN
FOR rec IN (
SELECT a.owner, a.table_name, a.constraint_name
FROM dba_constraints a
JOIN dba_constraints b
ON a.r_owner = b.owner
AND a.r_constraint_name = b.constraint_name
WHERE b.table_name = 'ORDERS'
AND a.constraint_type = 'R'
)
LOOP
EXECUTE IMMEDIATE
'ALTER TABLE ' || rec.owner || '.' || rec.table_name ||
' DISABLE CONSTRAINT ' || rec.constraint_name;
DBMS_OUTPUT.PUT_LINE('Disabled: ' || rec.constraint_name);
END LOOP;
-- 부모 테이블 PK 비활성화
EXECUTE IMMEDIATE 'ALTER TABLE orders DISABLE PRIMARY KEY';
DBMS_OUTPUT.PUT_LINE('Parent PK disabled successfully.');
END;
/
예방 방법
1. 제약 조건 변경 전 의존성 체크를 표준 절차로 수립하기
모든 제약 조건 관련 DDL 작업 전에 반드시 의존성 조회 쿼리를 실행하는 것을 팀 내 표준 절차로 만들어야 합니다. 특히 대규모 데이터 마이그레이션이나 배치 작업 전에 아래와 같은 전체 의존성 조회를 습관화하면 ORA-02297을 사전에 예방할 수 있습니다.
-- 스키마 전체의 FK 참조 관계 한눈에 파악
SELECT a.table_name AS child_table,
a.constraint_name AS fk_name,
b.table_name AS parent_table,
b.constraint_name AS pk_uk_name,
a.status AS fk_status
FROM dba_constraints a
JOIN dba_constraints b
ON a.r_owner = b.owner
AND a.r_constraint_name = b.constraint_name
WHERE a.constraint_type = 'R'
AND a.owner = 'MYSCHEMA' -- 대상 스키마명
ORDER BY b.table_name, a.table_name;
2. 제약 조건 비활성화/활성화 작업을 항상 트랜잭션 단위로 묶고, 롤백 계획 수립하기
제약 조건 변경 작업은 단독으로 실행하지 말고 반드시 활성화 복구 스크립트를 미리 준비해두어야 합니다. 작업 전에 현재 상태를 스냅샷으로 기록하고, 작업 실패 시 즉시 원복할 수 있는 스크립트를 준비해두는 것이 30년 현장 경험에서 나온 최고의 예방책입니다. 또한 CASCADE 옵션을 사용할 경우 어떤 FK가 비활성화되었는지 로그를 남겨두어야 활성화 시 누락이 없습니다.
관련 에러
- ORA-02266:
unique/primary keys in table referenced by enabled foreign keys— TRUNCATE 또는 DROP 시도 시 FK가 활성화된 상태에서 발생하며 ORA-02297과 유사한 맥락. - ORA-02298:
cannot validate - parent keys not found— FK를 ENABLE할 때 부모 테이블에 일치하는 키 값이 없을 경우 발생. 비활성화 후 재활성화 시 자주 마주치는 에러. - ORA-02449:
unique/primary keys in table referenced by foreign keys— 테이블 DROP 시 FK 의존성이 있을 때 발생. - ORA-00001:
unique constraint violated— 제약 조건 재활성화(ENABLE + VALIDATE) 시 중복 데이터가 존재할 경우 발생.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.