본문 바로가기
IT

ORA-12899 value too large for column — VARCHAR2 길이 초과 에러 원인·해결·예방

by 샤나엘 2026. 5. 13.
반응형

ORA-12899 value too large for column — VARCHAR2 길이 초과 에러 원인·해결·예방

Oracle Database에서 INSERT나 UPDATE 시 컬럼이 허용하는 길이보다 큰 값을 넣으려고 하면 ORA-12899: value too large for column 에러가 발생한다. 한국 환경에서는 단순 길이 초과뿐 아니라 한글 멀티바이트 처리, BYTE vs CHAR 시맨틱, 캐릭터셋 이관 같은 이슈로 자주 만난다.

 

본 글은 ORA-12899의 정확한 의미와 메시지 해석, 자주 발생하는 5가지 케이스, NLS_LENGTH_SEMANTICS의 BYTE·CHAR 차이, LENGTH·LENGTHB로 인코딩 문제 판별, 해결 방법(ALTER MODIFY·SUBSTR·VARCHAR2 N CHAR 설계)까지 정리한 트러블슈팅 자료다.

 

ORA-12899

이 글의 구성

 

01에러 메시지와 카테고리
02발생 원인 5가지
03NLS_LENGTH_SEMANTICS (BYTE vs CHAR)
04재현 시나리오와 코드 예제
05해결 방법과 디버깅 순서
Q&A자주 묻는 질문 5가지

01 에러 메시지와 카테고리

ORA-12899는 INSERT나 UPDATE가 컬럼이 허용하는 최대 길이를 초과하는 값을 대입하려 할 때 발생한다. 메시지에 컬럼 풀네임·실제 길이·최대 길이가 함께 표시되어 진단이 비교적 쉽다.

항목 내용
에러 코드 ORA-12899
영문 메시지 value too large for column "스키마"."테이블"."컬럼" (actual: 실제값, maximum: 최대값)
Cause (공식) An attempt was made to insert or update a value that is too wide for the destination column.
Action (공식) 컬럼을 더 넓히거나, 입력값을 SUBSTR로 잘라 적합한 크기로 만든 후 다시 시도
발생 영역 INSERT·UPDATE·MERGE·INSERT INTO SELECT 등 모든 데이터 입력 구문

핵심 관찰 — 메시지 읽기

ORA-12899 메시지의 actualmaximum 단위는 컬럼의 BYTE/CHAR 시맨틱에 따라 달라진다. BYTE 시맨틱이면 바이트 수, CHAR 시맨틱이면 문자 수다. 한글 환경에서는 두 단위가 다르게 작동해 길이가 같아 보여도 에러가 발생하는 경우가 흔하다.


02 발생 원인 5가지

원인 1 — 단순 길이 초과 (영문 기준)

VARCHAR2(10) 컬럼에 11자 이상의 영문 문자열을 INSERT할 때 발생하는 가장 단순한 케이스다.

원인 2 — 한글 멀티바이트 (BYTE 시맨틱)

VARCHAR2(10)이 BYTE 시맨틱이면 UTF-8 환경에서 한글 1자가 3바이트를 차지하므로 4자만 들어가도 12바이트가 되어 ORA-12899가 발생한다. 한글 환경에서 가장 흔한 케이스다.

원인 3 — INSERT INTO SELECT 컬럼 길이 불일치

원본 테이블 컬럼이 VARCHAR2(100)인데 대상 테이블이 VARCHAR2(50)인 경우, 원본 데이터 중 50자 초과 행에서 에러가 발생한다.

원인 4 — 캐릭터셋 이관 시 한글 팽창

EUC-KR(한글 1자 = 2바이트) DB의 데이터를 UTF-8(한글 1자 = 3바이트) DB로 이관할 때 BYTE 시맨틱 컬럼은 1.5배 더 많은 공간이 필요해 ORA-12899가 발생한다.

원인 5 — CHAR(N)에 더 긴 값 입력

CHAR(N)은 고정 길이 컬럼이지만, 더 긴 값을 입력하면 패딩이 아닌 ORA-12899로 거부된다. CHAR 사용 시 정확한 길이 관리가 필요하다.


03 NLS_LENGTH_SEMANTICS (BYTE vs CHAR)

VARCHAR2(N) 정의는 두 가지 시맨틱이 있다. 한글 환경에서 ORA-12899를 이해하는 핵심이다.

시맨틱 의미 한글 UTF-8 저장 가능 글자수
VARCHAR2(10) BYTE 10 바이트 한글 3자 (3×3=9바이트)
VARCHAR2(10 CHAR) 10 문자 한글 10자 (단, 최대 4000바이트 한도)

기본값은 BYTE이며 한글 환경에서 자주 문제가 된다. 세션·DB 기본값은 다음 쿼리로 확인한다.

-- 세션 기본 시맨틱 확인
SELECT value FROM nls_session_parameters
 WHERE parameter = 'NLS_LENGTH_SEMANTICS';

-- 컬럼별 시맨틱 확인 (CHAR_USED: 'B'=BYTE, 'C'=CHAR)
SELECT column_name, data_type, data_length, char_used
  FROM user_tab_columns
 WHERE table_name = 'EMP';

-- DB 캐릭터셋 확인
SELECT value FROM nls_database_parameters
 WHERE parameter = 'NLS_CHARACTERSET';

Oracle 공식 권장은 인스턴스 파라미터를 변경하기보다 컬럼별로 VARCHAR2(N CHAR)를 명시하는 방식이다. 인스턴스 설정 변경은 기존 객체와의 호환성 이슈가 생길 수 있다.


04 재현 시나리오와 코드 예제

원인 2 — 한글 멀티바이트 (가장 흔한 케이스)

-- UTF-8 환경, 기본 BYTE 시맨틱
CREATE TABLE emp (name VARCHAR2(10));  -- 10 BYTE

-- ✗ 한글 4자 = 12 바이트 → ORA-12899
INSERT INTO emp VALUES ('홍길동홍');
-- ORA-12899: value too large for column "...EMP"."NAME"
--   (actual: 12, maximum: 10)

-- ✓ CHAR 시맨틱으로 컬럼 재정의
CREATE TABLE emp2 (name VARCHAR2(10 CHAR));
INSERT INTO emp2 VALUES ('홍길동홍');  -- ✓ 정상

원인 3 — INSERT INTO SELECT 길이 불일치

-- src.note VARCHAR2(100), tgt.note VARCHAR2(50)

-- ✗ 원본에 50자 초과 행이 있으면 ORA-12899
INSERT INTO tgt (id, note) SELECT id, note FROM src;

-- ✓ SUBSTR로 잘라 넣기
INSERT INTO tgt (id, note)
SELECT id, SUBSTR(note, 1, 50) FROM src;

-- ✓ 또는 대상 컬럼 확장
ALTER TABLE tgt MODIFY (note VARCHAR2(100));

LENGTH vs LENGTHB로 원인 판별

-- 문자 수 vs 바이트 수 비교
SELECT LENGTH('홍길동') AS char_cnt,
       LENGTHB('홍길동') AS byte_cnt
  FROM dual;
-- UTF-8 환경: char_cnt=3, byte_cnt=9
-- EUC-KR 환경: char_cnt=3, byte_cnt=6

-- 문제 행 찾기 (BYTE 기준 50 초과)
SELECT id, note, LENGTHB(note) AS bytes
  FROM src
 WHERE LENGTHB(note) > 50;

05 해결 방법과 디버깅 순서

해결 방법

  1. 컬럼 확장ALTER TABLE T MODIFY (col VARCHAR2(100 CHAR));
  2. 데이터 자르기INSERT ... SELECT SUBSTR(col, 1, N) ...
  3. CHAR 시맨틱 사용 — 신규 컬럼은 VARCHAR2(N CHAR)로 명시
  4. 캐릭터셋 이관 시 사전 분석LENGTHB 기준 최대 길이를 확인 후 대상 컬럼 크기 조정

디버깅 순서

단계별 진단 절차

 

01에러 메시지의 컬럼명·actual·maximum을 확인한다.
02USER_TAB_COLUMNS로 컬럼 데이터 타입·길이·CHAR_USED('B'/'C')를 조회한다.
03DB 캐릭터셋(NLS_CHARACTERSET)을 확인한다.
04LENGTH와 LENGTHB를 비교해 멀티바이트 원인 여부를 판별한다.
05컬럼 확장(ALTER) 또는 입력 데이터 정제(SUBSTR) 중 결정한다.

06 자주 묻는 질문 5가지

Q1VARCHAR2(10)인데 한글 3자도 안 들어가는 경우가 있다

컬럼이 BYTE 시맨틱이고 DB 캐릭터셋이 UTF-8이라면 한글 1자가 3바이트라 VARCHAR2(10) 컬럼에는 3자 + α만 들어간다(9바이트 사용). 4자를 넣으면 12바이트가 되어 초과된다. 한글 데이터를 다루는 컬럼은 처음부터 VARCHAR2(N CHAR)로 정의하거나 컬럼 길이를 충분히 잡는 것이 안전하다.

Q2이관 후 갑자기 ORA-12899가 발생한다

캐릭터셋 변경(예: EUC-KR → UTF-8)으로 한글 바이트 수가 증가했을 가능성이 가장 높다. 같은 한글 문자라도 EUC-KR은 2바이트, UTF-8은 3바이트라 BYTE 시맨틱 컬럼에서는 1.5배 더 큰 공간이 필요하다. 이관 전 LENGTHB 기준 최대 길이를 분석해 대상 컬럼 크기를 사전 조정한다.

Q3VARCHAR2(N CHAR)가 모든 경우에 더 좋은가

한글·다국어 데이터에는 권장되지만 VARCHAR2의 최대 바이트 한도(기본 4000바이트, 확장 시 32767)는 동일하다. VARCHAR2(2000 CHAR)를 정의해도 실제 저장 가능한 바이트가 4000바이트를 넘으면 오류가 난다. 영문 전용 코드 컬럼은 BYTE 시맨틱이 더 직관적인 경우도 있다.

Q4NLS_LENGTH_SEMANTICS 인스턴스 파라미터를 CHAR로 바꿔도 되나

가능하지만 권장되지 않는다. 인스턴스 파라미터 변경은 기존 객체에 적용되지 않고 신규 생성 객체에만 영향을 주며, 일부 데이터 사전 객체와 호환성 이슈가 발생할 수 있다. Oracle 공식 가이드는 컬럼별로 VARCHAR2(N CHAR)를 명시하는 방식을 권장한다.

Q5운영 중인 테이블 컬럼을 확장해도 안전한가

VARCHAR2의 길이를 늘리는 ALTER MODIFY는 일반적으로 안전하고 빠르다. 메타데이터만 변경되므로 락 시간이 짧다. 단 BYTE → CHAR 시맨틱 변경은 의미가 다르고 일부 환경에서 데이터 재해석이 필요할 수 있어 사전 테스트가 필수다.


07 결론

ORA-12899는 메시지에 컬럼명·실제 길이·최대 길이가 함께 표시되어 원인 파악이 비교적 쉽지만, 한국 환경에서는 BYTE/CHAR 시맨틱 차이와 캐릭터셋 인코딩이 결합되어 진단이 까다로워질 수 있다.

 

실무 원칙은 다음과 같다.

 

첫째, 한글·다국어 데이터를 다루는 컬럼은 처음부터 VARCHAR2(N CHAR)로 정의해 시맨틱 혼란을 줄인다.

둘째, 이관 작업 전 LENGTHB 기준 최대 길이 분석을 통해 대상 컬럼 크기를 사전 조정한다.

셋째, 메시지의 actual·maximum 단위가 BYTE인지 CHAR인지를 컬럼의 CHAR_USED로 함께 확인한다.

ORA-12899의 메시지는 친절하지만 한글 환경의 BYTE/CHAR 시맨틱 차이를 함께 봐야 한다. LENGTH·LENGTHB 비교가 가장 빠른 진단 도구.

 

— 한글 컬럼은 VARCHAR2(N CHAR), 이관 시 LENGTHB 사전 분석

트러블슈팅 체크리스트

 

01에러 메시지의 컬럼명·actual·maximum을 정확히 추출한다.
02USER_TAB_COLUMNS로 컬럼 데이터 타입·길이·CHAR_USED를 확인한다.
03DB 캐릭터셋(NLS_CHARACTERSET)을 점검한다.
04LENGTH와 LENGTHB 비교로 멀티바이트 원인을 판별한다.
05한글 컬럼은 VARCHAR2(N CHAR)로 정의한다.
06컬럼 확장이 어렵다면 SUBSTR로 데이터를 자른다.
07캐릭터셋 이관 전 LENGTHB 최대값을 분석한다.

본 글은 Oracle Database 컬럼 길이 에러 ORA-12899의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.

 

#ORA12899 #valuetoolargeforcolumn #오라클에러 #VARCHAR2 #NLSLENGTHSEMANTICS #BYTECHAR #한글인코딩 #LENGTHB #LENGTH #ALTERMODIFY #SUBSTR #캐릭터셋 #UTF8 #EUCKR #DB트러블슈팅

반응형

댓글