2026년 10월 20일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-00001 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-00001 unique constraint violated 는?
ORA-00001 에러는 Oracle 데이터베이스에서 UNIQUE 제약 조건 또는 PRIMARY KEY 제약 조건이 설정된 컬럼에 이미 존재하는 값을 INSERT하거나 UPDATE하려 할 때 발생합니다. 즉, 테이블 내에서 반드시 유일해야 하는 값이 중복될 때 Oracle이 데이터 무결성을 보호하기 위해 해당 작업을 거부하고 이 에러를 반환합니다. 실무에서는 대량 데이터 마이그레이션, 배치 작업, 동시 트랜잭션 처리 등 다양한 상황에서 빈번하게 마주치는 에러 중 하나입니다.
주요 발생 원인
1. 중복 데이터 INSERT 시도
가장 흔한 원인으로, 이미 테이블에 존재하는 PRIMARY KEY 또는 UNIQUE KEY 값을 다시 삽입하려는 경우입니다. 특히 외부 시스템에서 데이터를 가져오거나 애플리케이션 단에서 중복 체크 없이 INSERT 쿼리를 실행할 때 자주 발생합니다. 시퀀스(SEQUENCE) 없이 수동으로 ID를 관리하거나 시퀀스 값이 리셋된 경우에도 이 문제가 나타납니다.
2. 동시 트랜잭션(Concurrent Transaction)에 의한 충돌
두 개 이상의 세션이 동시에 동일한 UNIQUE 값을 INSERT하려 할 때 발생합니다. 첫 번째 트랜잭션이 COMMIT되기 전까지 두 번째 트랜잭션은 대기하다가, COMMIT 이후 중복이 감지되어 에러가 발생합니다. 멀티스레드 애플리케이션이나 높은 동시성 환경에서 특히 주의가 필요한 케이스입니다.
3. 배치 작업 또는 데이터 마이그레이션 시 중복 레코드 존재
대용량 데이터를 일괄로 INSERT할 때 원본 데이터 자체에 중복이 포함되어 있거나, 이미 타겟 테이블에 존재하는 데이터를 다시 적재하는 경우에 발생합니다. ETL 작업이나 데이터 이관 프로젝트에서 매우 빈번하게 나타나며, 에러 처리 로직이 없으면 전체 배치가 실패하는 치명적인 상황으로 이어질 수 있습니다.
해결 방법
원인 1 해결: 중복 여부 사전 확인 후 INSERT
INSERT 전에 해당 데이터가 이미 존재하는지 확인하거나, MERGE 문을 활용하여 중복 시 UPDATE, 없으면 INSERT하는 UPSERT 패턴을 사용하는 것이 효과적입니다.
-- 방법 1: INSERT 전 중복 체크
DECLARE
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count
FROM employees
WHERE employee_id = 1001;
IF v_count = 0 THEN
INSERT INTO employees (employee_id, name, department)
VALUES (1001, '홍길동', 'IT');
COMMIT;
ELSE
DBMS_OUTPUT.PUT_LINE('이미 존재하는 데이터입니다: employee_id = 1001');
END IF;
END;
/
-- 방법 2: MERGE 문을 활용한 UPSERT
MERGE INTO employees tgt
USING (SELECT 1001 AS employee_id, '홍길동' AS name, 'IT' AS department FROM dual) src
ON (tgt.employee_id = src.employee_id)
WHEN MATCHED THEN
UPDATE SET tgt.name = src.name,
tgt.department = src.department
WHEN NOT MATCHED THEN
INSERT (employee_id, name, department)
VALUES (src.employee_id, src.name, src.department);
COMMIT;
원인 2 해결: 동시성 제어를 위한 예외 처리
동시 트랜잭션 환경에서는 예외 처리 블록을 사용하여 ORA-00001 발생 시 적절한 후속 처리를 수행하도록 합니다.
-- PL/SQL 예외 처리로 동시성 충돌 대응
DECLARE
v_employee_id NUMBER := 1001;
BEGIN
INSERT INTO employees (employee_id, name, department)
VALUES (v_employee_id, '홍길동', 'IT');
COMMIT;
DBMS_OUTPUT.PUT_LINE('INSERT 성공');
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- ORA-00001 발생 시 UPDATE로 대체 처리
UPDATE employees
SET name = '홍길동',
department = 'IT',
updated_at = SYSDATE
WHERE employee_id = v_employee_id;
COMMIT;
DBMS_OUTPUT.PUT_LINE('중복 감지: UPDATE로 처리 완료');
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('예상치 못한 에러: ' || SQLERRM);
END;
/
원인 3 해결: 배치 작업 시 중복 제거 및 안전한 INSERT
-- 원본 데이터에서 중복 제거 후 INSERT
INSERT INTO employees (employee_id, name, department)
SELECT employee_id, name, department
FROM (
SELECT employee_id, name, department,
ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY created_at DESC) AS rn
FROM staging_employees
) t
WHERE t.rn = 1
AND NOT EXISTS (
SELECT 1 FROM employees e
WHERE e.employee_id = t.employee_id
);
COMMIT;
-- 이미 존재하는 데이터를 제외하고 INSERT (MINUS 활용)
INSERT INTO employees (employee_id, name, department)
SELECT employee_id, name, department FROM staging_employees
MINUS
SELECT employee_id, name, department FROM employees;
COMMIT;
-- 에러 발생 시 해당 행만 건너뛰는 방법 (Oracle 10g 이상)
INSERT INTO employees (employee_id, name, department)
SELECT employee_id, name, department
FROM staging_employees
LOG ERRORS INTO err$_employees ('BATCH_JOB_20240101') REJECT LIMIT UNLIMITED;
COMMIT;
예방 방법
1. 시퀀스(SEQUENCE)와 트리거를 활용한 자동 키 생성
수동으로 PRIMARY KEY 값을 관리하는 것은 중복 발생 위험이 높습니다. Oracle SEQUENCE를 사용하거나, Oracle 12c 이상에서는 IDENTITY 컬럼을 활용하여 키 값을 자동으로 생성함으로써 중복 가능성을 원천 차단하는 것이 Best Practice입니다.
-- Oracle 12c 이상: IDENTITY 컬럼 활용
CREATE TABLE employees (
employee_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR2(100) NOT NULL,
department VARCHAR2(50),
created_at DATE DEFAULT SYSDATE
);
-- Oracle 11g 이하: SEQUENCE + TRIGGER 활용
CREATE SEQUENCE emp_seq START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE OR REPLACE TRIGGER trg_employees_bi
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
IF :NEW.employee_id IS NULL THEN
SELECT emp_seq.NEXTVAL INTO :NEW.employee_id FROM dual;
END IF;
END;
/
2. 애플리케이션 레벨에서의 입력 데이터 유효성 검증 강화
데이터베이스 제약 조건에만 의존하지 않고, 애플리케이션 단에서도 INSERT 또는 UPDATE 전에 반드시 중복 여부를 확인하는 로직을 구현해야 합니다. 또한 정기적으로 UNIQUE 제약 조건 현황을 점검하고, 제약 조건 위반 에러 로그를 모니터링하는 프로세스를 운영 체계에 포함시키는 것이 재발 방지의 핵심입니다.
관련 에러
- ORA-00003: 내부 UNIQUE 제약 조건 관련 에러로, 시스템 내부 처리 중 발생하는 유사 케이스입니다.
- ORA-02291: FOREIGN KEY 제약 조건 위반 에러로, 참조하는 부모 테이블에 해당 키가 존재하지 않을 때 발생합니다.
- ORA-02292: 자식 레코드가 존재하는 부모 레코드를 삭제하려 할 때 발생하는 참조 무결성 에러입니다.
- ORA-02449: UNIQUE/PRIMARY KEY를 가진 테이블을 DROP하려 할 때, 해당 키를 참조하는 FOREIGN KEY가 존재하면 발생합니다.
- ORA-00060: 동시 트랜잭션 처리 중 DEADLOCK이 감지될 때 발생하며, ORA-00001과 함께 동시성 문제의 주요 에러입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.