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

ORA-12704
2026년 09월 15일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-12704 character set mismatch 는?

ORA-12704는 Oracle SQL 문에서 서로 다른 문자셋(Character Set)을 가진 데이터나 컬럼을 비교하거나 결합하려 할 때 발생하는 오류입니다. 예를 들어, NVARCHAR2 타입의 컬럼과 VARCHAR2 타입의 컬럼을 직접 비교하거나, 문자열 리터럴을 NCHAR/NVARCHAR2 컬럼과 함께 사용할 때 이 에러가 빈번히 나타납니다. 특히 다국어를 지원하는 글로벌 시스템이나 마이그레이션 작업 중에 자주 마주치는 에러로, 방치할 경우 애플리케이션 전체 장애로 이어질 수 있습니다.


주요 발생 원인

  • VARCHAR2와 NVARCHAR2 타입 간 직접 비교 또는 결합

Oracle에서 VARCHAR2는 데이터베이스 문자셋(Database Character Set, 예: AL32UTF8, KO16MSWIN949)을 사용하고, NVARCHAR2는 내셔널 문자셋(National Character Set, 예: AL16UTF16)을 사용합니다. 이 두 타입을 명시적인 변환 없이 WHERE 절이나 UNION, CONCAT 등에서 함께 사용하면 Oracle 옵티마이저가 문자셋 불일치를 감지하고 ORA-12704를 발생시킵니다. 실무에서 레거시 시스템을 신규 시스템과 연동할 때 가장 흔하게 나타나는 패턴입니다.

  • 문자열 리터럴과 NCHAR/NVARCHAR2 컬럼 비교 시 접두사 누락

NCHAR 또는 NVARCHAR2 타입의 컬럼과 비교할 때, 일반 문자열 리터럴('값')은 VARCHAR2로 처리되므로 문자셋 충돌이 발생합니다. NCHAR 계열의 컬럼과 비교하려면 반드시 내셔널 문자셋 리터럴 접두사인 N을 붙여야(N'값') 하는데, 이를 놓치는 경우가 매우 많습니다. 개발자들이 ORM 프레임워크나 동적 쿼리 생성 시 이 접두사를 자동으로 처리하지 않아 운영 환경에서 예기치 않게 터지는 경우가 많습니다.

  • 데이터베이스 링크(DB Link)를 통한 서로 다른 문자셋의 원격 DB 접근

DB Link를 통해 원격 데이터베이스의 테이블과 로컬 테이블을 JOIN하거나 비교할 때, 두 데이터베이스의 문자셋이 다르면 ORA-12704가 발생할 수 있습니다. 예를 들어, 로컬 DB가 AL32UTF8이고 원격 DB가 KO16MSWIN949라면, 직접 비교 시 Oracle이 자동으로 변환하지 못하는 경우가 발생합니다. 특히 이기종 DB 환경을 통합하는 프로젝트에서 자주 발생하며, 데이터 이관 스크립트 작성 시 반드시 주의해야 합니다.


해결 방법

원인 1 해결: VARCHAR2와 NVARCHAR2 간 타입 변환

TO_NCHAR() 또는 TO_CHAR() 함수를 이용해 명시적으로 타입을 통일시킵니다.

-- 문제 발생 쿼리 (ORA-12704 발생)
SELECT *
FROM employees e
WHERE e.nvarchar_col = e.varchar_col;  -- 타입 불일치

-- 해결책 1: VARCHAR2를 NVARCHAR2로 변환
SELECT *
FROM employees e
WHERE e.nvarchar_col = TO_NCHAR(e.varchar_col);

-- 해결책 2: NVARCHAR2를 VARCHAR2로 변환
SELECT *
FROM employees e
WHERE TO_CHAR(e.nvarchar_col) = e.varchar_col;

-- UNION 사용 시 문자셋 통일 예시
SELECT TO_NCHAR(department_name) AS dept_name FROM departments_old
UNION ALL
SELECT department_name FROM departments_new;  -- departments_new의 컬럼이 NVARCHAR2인 경우

원인 2 해결: NCHAR/NVARCHAR2 컬럼과 리터럴 비교 시 N 접두사 사용

-- 문제 발생 쿼리 (ORA-12704 발생)
SELECT *
FROM customers
WHERE national_name = '홍길동';  -- 일반 리터럴 사용, 문자셋 불일치

-- 해결책: N 접두사 사용
SELECT *
FROM customers
WHERE national_name = N'홍길동';  -- 내셔널 문자셋 리터럴 사용

-- 파라미터 바인딩을 사용하는 동적 쿼리에서의 처리 예시
-- PL/SQL 블록에서의 올바른 사용법
DECLARE
    v_name NVARCHAR2(100);
    v_count NUMBER;
BEGIN
    v_name := N'홍길동';  -- NVARCHAR2 변수에 할당
    
    SELECT COUNT(*)
    INTO v_count
    FROM customers
    WHERE national_name = v_name;  -- 같은 타입끼리 비교
    
    DBMS_OUTPUT.PUT_LINE('건수: ' || v_count);
END;
/

-- CONCAT 사용 시 주의사항
-- 잘못된 예
SELECT CONCAT(nvarchar2_col, ' suffix') FROM my_table;  -- ORA-12704

-- 올바른 예
SELECT CONCAT(nvarchar2_col, N' suffix') FROM my_table;
-- 또는 TO_CHAR로 변환
SELECT TO_CHAR(nvarchar2_col) || ' suffix' FROM my_table;

원인 3 해결: DB Link 사용 시 명시적 변환

-- DB Link를 통한 원격 테이블 조회 시 문자셋 명시적 변환
-- 문제 발생 쿼리
SELECT l.emp_name, r.dept_name
FROM local_employees l
JOIN remote_departments@db_link_name r ON l.dept_id = r.dept_id
WHERE l.emp_name = r.manager_name;  -- 문자셋 불일치 가능

-- 해결책: CONVERT 함수로 문자셋 통일
SELECT l.emp_name, r.dept_name
FROM local_employees l
JOIN remote_departments@db_link_name r ON l.dept_id = r.dept_id
WHERE l.emp_name = CONVERT(r.manager_name, 'AL32UTF8', 'KO16MSWIN949');

-- 현재 DB의 문자셋 확인 쿼리 (문제 파악에 필수)
SELECT *
FROM nls_database_parameters
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');

-- 컬럼의 데이터 타입 확인
SELECT column_name, data_type, char_used
FROM all_tab_columns
WHERE table_name = 'YOUR_TABLE_NAME'
  AND owner = 'YOUR_SCHEMA';

세션 레벨에서의 임시 해결 방법

-- 세션 레벨 NLS 설정 변경 (임시 방편)
ALTER SESSION SET NLS_NCHAR_CONV_EXCP = FALSE;

-- 문자셋 변환 함수 활용 종합 예제
SELECT 
    employee_id,
    TO_CHAR(national_name) AS name_varchar,
    CONVERT(address, 'AL32UTF8') AS address_utf8
FROM employees
WHERE TO_CHAR(national_name) LIKE '%홍%';

예방 방법

  • 데이터 모델 설계 단계에서 문자 타입 통일 원칙 수립

신규 시스템 설계 시 NCHAR/NVARCHAR2 타입의 사용을 최소화하고, 가능하면 VARCHAR2와 데이터베이스 문자셋(AL32UTF8 권장)으로 통일하는 표준을 수립해야 합니다. 다국어 지원이 필요한 경우에도 AL32UTF8 문자셋 하나로 VARCHAR2 타입을 사용하면 NCHAR 계열과의 혼용을 피할 수 있습니다. 테이블 설계 리뷰 체크리스트에 “NCHAR/NVARCHAR2 사용 여부 및 혼용 방지” 항목을 반드시 포함시키십시오.

  • 개발 초기 단계에서 문자셋 충돌 자동 검출 쿼리 활용

운영 배포 전에 아래 쿼리를 CI/CD 파이프라인이나 코드 리뷰 체크리스트에 포함하여 문자 타입 혼용 여부를 사전에 검출하는 습관을 들이십시오. 또한 DB Link로 연결되는 원격 데이터베이스의 문자셋을 DBA 문서에 명시하고, 연결 시마다 CONVERT 함수 적용 여부를 확인하는 절차를 표준화해야 합니다.

-- 동일 테이블 내 CHAR 계열과 NCHAR 계열 혼용 컬럼 탐지 쿼리
SELECT 
    table_name,
    SUM(CASE WHEN data_type IN ('CHAR','VARCHAR2') THEN 1 ELSE 0 END) AS varchar_count,
    SUM(CASE WHEN data_type IN ('NCHAR','NVARCHAR2') THEN 1 ELSE 0 END) AS nvarchar_count
FROM all_tab_columns
WHERE owner = 'YOUR_SCHEMA'
GROUP BY table_name
HAVING 
    SUM(CASE WHEN data_type IN ('CHAR','VARCHAR2') THEN 1 ELSE 0 END) > 0
    AND SUM(CASE WHEN data_type IN ('NCHAR','NVARCHAR2') THEN 1 ELSE 0 END) > 0
ORDER BY table_name;

관련 에러

  • ORA-12705: Cannot access NLS data files or invalid environment specified — NLS 환경 설정 자체가 잘못된 경우 발생하며, ORA-12704와 함께 나타나기도 합니다.
  • ORA-06502: PL/SQL: numeric or value error: character string buffer too small — 문자셋 변환 과정에서 데이터 길이가 늘어나 버퍼 초과 시 연쇄 발생할 수 있습니다.
  • ORA-01401 / ORA-12899: value too large for column — CONVERT 함수로 문자셋을 변환할 때 바이트 길이 차이로 인해 타겟 컬럼 크기를 초과할 경우 발생합니다.
  • ORA-00910: specified length too long for its datatype — NCHAR 컬럼 정의 시 문자셋 특성을 고려하지 않은 길이 지정 시 발생하며, 문자셋 관련 설계 오류와 연관됩니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기