2026년 07월 31일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-01779 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-01779 cannot modify a column which maps to a non key-preserved table 는?
ORA-01779 에러는 조인 뷰(Join View) 또는 복잡한 뷰(Complex View)를 통해 DML(INSERT, UPDATE, DELETE) 작업을 시도할 때, 수정하려는 컬럼이 키 보존(Key-Preserved) 테이블에 속하지 않는 경우 발생합니다. 키 보존 테이블이란 뷰 내에서 해당 테이블의 기본 키(Primary Key) 또는 유니크 키(Unique Key)가 유일성을 유지하고 있는 테이블을 의미합니다. Oracle은 데이터 무결성을 보호하기 위해 키 보존이 보장되지 않는 테이블의 컬럼은 뷰를 통해 직접 수정하는 것을 허용하지 않습니다.
주요 발생 원인
- 조인 뷰에서 비키 보존 테이블 컬럼 수정 시도
가장 빈번하게 발생하는 원인으로, 두 개 이상의 테이블을 조인한 뷰에서 DML을 수행할 때 발생합니다. 예를 들어 1:N 관계에서 N 쪽 테이블(Detail 테이블)은 조인 결과에서 동일한 키 값이 여러 번 나타날 수 있기 때문에 키 보존이 되지 않습니다. 이 경우 해당 테이블의 컬럼을 뷰를 통해 UPDATE 또는 DELETE하려 하면 ORA-01779가 발생합니다.
- INSTEAD OF 트리거 없이 복잡한 뷰에 DML 시도
GROUP BY, DISTINCT, UNION, 집계 함수 등이 포함된 복잡한 뷰는 기본적으로 DML이 불가능합니다. 개발자가 뷰의 복잡도를 인지하지 못하고 단순 테이블처럼 UPDATE를 시도할 때 이 에러가 발생합니다. 이러한 뷰는 INSTEAD OF 트리거를 생성해야만 DML 처리가 가능합니다.
- BYPASS_UJVC 힌트 미사용 또는 잘못된 뷰 설계
과거 Oracle 버전에서는 /+ BYPASS_UJVC / 힌트를 사용하여 키 보존 검사를 우회할 수 있었지만, Oracle 11g 이후부터는 이 힌트가 더 이상 지원되지 않습니다. 뷰를 설계할 때 어느 테이블이 키 보존되는지 고려하지 않고 뷰를 생성하면, 나중에 DML 시도 시 반드시 이 에러를 마주치게 됩니다. 따라서 뷰 설계 단계에서부터 DML 허용 여부를 명확히 정의해야 합니다.
해결 방법
해결책 1: 뷰 대신 기본 테이블에 직접 DML 수행
가장 간단하고 확실한 방법은 뷰를 우회하여 원본 테이블에 직접 DML을 수행하는 것입니다.
-- 문제 발생 예시: 조인 뷰를 통한 UPDATE 시도
CREATE VIEW emp_dept_view AS
SELECT e.employee_id, e.first_name, e.salary, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;
-- ORA-01779 발생: departments는 키 보존 테이블이 아님
UPDATE emp_dept_view
SET department_name = 'IT Operations'
WHERE department_id = 10;
-- 해결: 기본 테이블에 직접 UPDATE
UPDATE departments
SET department_name = 'IT Operations'
WHERE department_id = 10;
해결책 2: INSTEAD OF 트리거 생성
뷰를 통한 DML이 반드시 필요한 경우, INSTEAD OF 트리거를 생성하여 DML 로직을 직접 제어합니다.
-- INSTEAD OF 트리거 생성
CREATE OR REPLACE TRIGGER trg_emp_dept_view_update
INSTEAD OF UPDATE ON emp_dept_view
FOR EACH ROW
BEGIN
-- 키 보존 테이블(employees)에 대한 UPDATE
IF :NEW.salary != :OLD.salary THEN
UPDATE employees
SET salary = :NEW.salary
WHERE employee_id = :OLD.employee_id;
END IF;
-- 비키 보존 테이블(departments)에 대한 UPDATE
IF :NEW.department_name != :OLD.department_name THEN
UPDATE departments
SET department_name = :NEW.department_name
WHERE department_name = :OLD.department_name;
END IF;
END;
/
-- 트리거 생성 후 뷰를 통한 UPDATE 가능
UPDATE emp_dept_view
SET department_name = 'IT Operations',
salary = 7000
WHERE employee_id = 100;
해결책 3: 키 보존 테이블만 수정하도록 뷰 재설계
조인 뷰에서 키 보존 테이블의 컬럼만 수정하도록 쿼리를 재작성합니다.
-- 키 보존 여부 확인: USER_UPDATABLE_COLUMNS 뷰 활용
SELECT column_name, updatable, insertable, deletable
FROM user_updatable_columns
WHERE table_name = 'EMP_DEPT_VIEW';
-- COLUMN_NAME UPDATABLE INSERTABLE DELETABLE
-- -------------- --------- ---------- ---------
-- EMPLOYEE_ID YES YES YES
-- FIRST_NAME YES YES YES
-- SALARY YES YES YES
-- DEPARTMENT_NAME NO NO NO
-- 키 보존 컬럼(employees 테이블 컬럼)만 수정 → 정상 작동
UPDATE emp_dept_view
SET salary = 8000,
first_name = 'John'
WHERE employee_id = 100;
-- WITH CHECK OPTION을 활용한 뷰 재생성 (안전한 DML 보장)
CREATE OR REPLACE VIEW emp_only_view AS
SELECT e.employee_id, e.first_name, e.last_name, e.salary, e.department_id
FROM employees e
WITH CHECK OPTION CONSTRAINT emp_view_chk;
-- 위 뷰는 employees 테이블만 포함하므로 DML 정상 작동
UPDATE emp_only_view
SET salary = 9000
WHERE employee_id = 100;
해결책 4: MERGE 문 활용
복잡한 조인 상황에서는 MERGE 문을 활용하여 우아하게 처리할 수 있습니다.
-- MERGE를 사용한 안전한 데이터 수정
MERGE INTO departments d
USING (
SELECT DISTINCT department_id, 'IT Operations' AS new_dept_name
FROM employees
WHERE department_id = 10
) src
ON (d.department_id = src.department_id)
WHEN MATCHED THEN
UPDATE SET d.department_name = src.new_dept_name;
예방 방법
- 뷰 생성 시 USER_UPDATABLE_COLUMNS로 DML 가능 여부 사전 검증
뷰를 생성한 직후 반드시 USER_UPDATABLE_COLUMNS 딕셔너리 뷰를 조회하여 어느 컬럼이 DML 가능한지 문서화해야 합니다. 뷰를 통한 DML이 필요한 컬럼이 UPDATABLE = NO로 나온다면, 설계 단계에서 INSTEAD OF 트리거 구현 계획을 세워야 합니다. 이 습관 하나만으로도 운영 중 발생하는 ORA-01779 에러의 대부분을 사전에 차단할 수 있습니다.
- DML이 필요한 뷰는 단일 테이블 기반 또는 키 보존 설계 원칙 준수
뷰를 설계할 때 DML 수행이 예상되는 경우, 가능한 한 단일 테이블 기반 뷰를 사용하거나, 조인 뷰를 사용한다면 반드시 기본 키 또는 유니크 키가 포함되어 키 보존이 보장되는 구조로 설계해야 합니다. 조인 뷰의 경우 1:1 관계에서는 양쪽 모두 키 보존이 가능하지만, 1:N 관계에서는 1 쪽 테이블만 키 보존이 보장됩니다. 이 원칙을 코딩 가이드라인에 포함시켜 개발팀 전체가 공유하는 것이 중요합니다.
관련 에러
- ORA-01732: 이 뷰에 대한 데이터 조작 조작이 적합하지 않습니다. 집계 함수, GROUP BY, DISTINCT 등이 포함된 뷰에서 DML 시도 시 발생합니다.
- ORA-01733: 가상 컬럼은 여기에 허용되지 않습니다. 함수나 표현식으로 만들어진 가상 컬럼에 DML을 시도할 때 발생합니다.
- ORA-01402: 뷰의 WITH CHECK OPTION 조건 위반. WITH CHECK OPTION이 설정된 뷰에서 뷰의 WHERE 조건을 위반하는 DML 시도 시 발생합니다.
- ORA-01031: 권한이 부족합니다. 뷰 DML 관련 객체 권한이 없을 때 발생하며, ORA-01779와 함께 뷰 DML 문제 진단 시 함께 확인해야 할 에러입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.