ORA-01438 value larger than specified precision — NUMBER 정밀도 초과 에러 원인·해결·예방
Oracle Database에서 INSERT나 UPDATE 시 NUMBER 컬럼에 정의된 정밀도(precision)를 초과하는 값을 넣으려고 하면 ORA-01438: value larger than specified precision allowed for this column 에러가 발생한다. NUMBER(p, s)의 정수부·소수부 자릿수 관계를 정확히 이해해야 빠르게 해결할 수 있다.
본 글은 ORA-01438의 정확한 의미와 NUMBER(p, s) 정밀도·스케일 공식, 자주 발생하는 5가지 케이스, 해결 방법(ALTER MODIFY·ROUND·TRUNC·CAST), 유사 에러 ORA-12899(VARCHAR2)와의 차이까지 정리한 트러블슈팅 자료다.

이 글의 구성
01 에러 메시지와 NUMBER 정밀도
| 항목 | 내용 |
|---|---|
| 에러 코드 | ORA-01438 |
| 영문 메시지 | value larger than specified precision allowed for this column |
| Cause (공식) | When inserting or updating records in a column, the precision exceeded that specified by the column definition. |
| Action (공식) | 값을 컬럼 정의에 맞게 수정하거나, 컬럼의 precision을 확장 |
| 발생 영역 | INSERT·UPDATE·MERGE의 NUMBER 컬럼 대상 |
NUMBER(p, s) 정밀도와 스케일
- p (precision): 총 유효 숫자 자릿수 (1~38 범위)
- s (scale): 소수점 이하 자릿수
- 정수부 허용 자릿수 = p − s
- 소수부 허용 자릿수 = s
핵심 관찰 — 정수부 자릿수가 핵심
NUMBER(5, 2)는 총 5자리 중 소수부 2자리, 정수부는 5 − 2 = 3자리만 허용한다. 따라서 999.99까지 저장 가능하고 1000.00 이상은 ORA-01438이 발생한다. 흔히 "총 5자리"라고만 생각하면 자주 헷갈리는 부분이다.
02 발생 원인 5가지
원인 1 — 정수부 자릿수 초과
NUMBER(3, 2)에 12.34를 넣으면 정수부가 1자리만 허용되는데 입력값은 2자리라 발생한다. 가장 흔한 패턴이다.
원인 2 — INSERT INTO SELECT 정밀도 불일치
원본 컬럼이 NUMBER(10, 2)인데 대상이 NUMBER(5, 2)인 경우, 원본 데이터 중 정수부 3자리 초과 행에서 발생한다.
원인 3 — 계산 결과의 정밀도 초과
곱셈·합계 같은 산술 연산 결과가 컬럼 정밀도를 초과하는 경우다. 평소 정상 범위 값이라도 계산 결과는 큰 값이 될 수 있다.
원인 4 — 음수 스케일 NUMBER(p, -s)
스케일이 음수인 경우 정수부 끝자리에서 반올림 단위가 결정된다. NUMBER(5, -2)는 100단위 반올림으로 저장하며 일정 범위를 초과하면 발생한다.
원인 5 — 데이터 마이그레이션 후 정밀도 변화
기존 테이블 컬럼 정의가 변경됐거나, 외부 시스템에서 들어오는 값의 단위가 달라진 경우(원·천원 단위 혼용 등)에 발생한다.
03 재현 시나리오와 코드 예제
원인 1 — 정수부 자릿수 초과
CREATE TABLE price (val NUMBER(5, 2));
-- 정수부 3자리(5-2), 소수부 2자리 → 최대 999.99
-- ✗ 정수부 4자리 초과
INSERT INTO price VALUES (12345.67);
-- ORA-01438: value larger than specified precision
-- ✓ 컬럼 확장
ALTER TABLE price MODIFY (val NUMBER(10, 2));
INSERT INTO price VALUES (12345.67); -- 정상
원인 2 — INSERT SELECT 정밀도 불일치
-- src.val NUMBER(10,2), tgt.val NUMBER(5,2)
-- ✗ 원본에 999.99 초과 행이 있으면 ORA-01438
INSERT INTO tgt (id, val) SELECT id, val FROM src;
-- ✓ ROUND·TRUNC로 정제 또는 사전 검증
SELECT id, val FROM src WHERE val > 999.99; -- 위반 행 확인
INSERT INTO tgt (id, val)
SELECT id, CASE WHEN val > 999.99 THEN 999.99 ELSE val END
FROM src;
원인 3 — 계산 결과 정밀도 초과
-- total NUMBER(5,2) — 999.99 한도
-- ✗ qty × price 결과가 한도 초과
INSERT INTO order_total (total)
SELECT qty * price FROM orders;
-- ORA-01438 (50개 × 30원 = 1500 → 정수부 4자리)
-- ✓ ROUND·CAST로 정밀도 명시
INSERT INTO order_total (total)
SELECT CAST(qty * price AS NUMBER(10, 2)) FROM orders;
04 해결 방법과 디버깅 순서
해결 방법 4가지
| 방법 | 설명 |
|---|---|
| 컬럼 확장 | ALTER TABLE T MODIFY (col NUMBER(p2, s2))로 정밀도 확장 |
| ROUND·TRUNC | 소수부 정밀도 맞추기 (정수부 초과에는 효과 없음) |
| CASE·CAST | 조건 분기로 한도 초과 시 대체값 처리 |
| 사전 검증 | SELECT WHERE val >= POWER(10, p-s)로 위반 행 추출 |
디버깅 순서
단계별 진단 절차
05 ORA-12899와의 차이
ORA-01438과 ORA-12899는 둘 다 "컬럼 한도 초과" 에러이지만 데이터 타입이 다르다.
| 에러 | 대상 데이터 타입 | 메시지 정보 |
|---|---|---|
| ORA-01438 | NUMBER (숫자) | 컬럼명·실제값 미포함 (덜 친절) |
| ORA-12899 | VARCHAR2·CHAR (문자) | 컬럼명·actual·maximum 포함 (디버깅 용이) |
ORA-12899는 메시지에 컬럼명과 actual/maximum이 친절하게 표시되지만, ORA-01438은 그런 정보가 없어 대상 컬럼을 직접 찾아내야 한다. SQL 문맥과 USER_TAB_COLUMNS 조회로 좁힌다.
ORA-01438은 NUMBER(p, s)의 정수부 = p − s 자리 공식을 이해하는 것이 출발점이다. 단순 "총 자릿수"가 아닌 정수부·소수부 분리 계산이 핵심.
— 메시지에 컬럼명 없음, USER_TAB_COLUMNS로 직접 좁혀야 함
06 자주 묻는 질문 5가지
Q1NUMBER(5)와 NUMBER(5, 0)는 같은가
같다. 스케일을 지정하지 않으면 기본값 0이다. 둘 다 정수부 5자리(최대 99999)를 허용하고 소수부는 저장하지 않는다.
Q2ROUND로 정밀도 문제를 모두 해결할 수 있나
ROUND는 소수부 자릿수 초과에만 효과적이다. 정수부 자릿수가 초과된 경우에는 ROUND를 해도 자릿수가 줄지 않아 여전히 ORA-01438이 발생한다. 정수부 초과는 컬럼 확장이나 CASE 분기로 처리한다.
Q3운영 테이블 NUMBER 컬럼을 확장해도 안전한가
NUMBER precision을 늘리는 ALTER MODIFY는 일반적으로 안전하다. 메타데이터만 변경되므로 락 시간이 짧고 기존 데이터에 영향 없다. 다만 precision을 줄이거나 scale을 바꾸는 경우는 기존 데이터 호환성을 확인해야 한다.
Q4음수 스케일은 언제 쓰나
NUMBER(p, -s)는 정수부 끝자리에서 반올림되는 형태다. 예: NUMBER(5, -2)는 100단위로 반올림해 저장한다. 통계·집계용 대략적 큰 수를 저장할 때 사용되지만 일반 업무에서는 거의 쓰지 않는다.
Q5왜 ORA-01438은 컬럼명을 알려주지 않나
Oracle 구버전부터 정의된 에러 메시지 포맷이 단순해서 컬럼명이 포함되지 않는다. ORA-12899처럼 메시지가 친절하지 않으므로 SQL 문맥과 데이터 사전 조회로 직접 좁혀야 한다. 신버전에서 메시지 개선이 일부 적용된다는 보고는 있지만 일반적으로는 동일하다.
07 결론
ORA-01438은 NUMBER(p, s) 정의의 정수부·소수부 자릿수 관계를 정확히 이해해야 빠르게 해결할 수 있다. 단순한 자릿수 초과처럼 보이지만 계산 결과·INSERT INTO SELECT·마이그레이션 같은 다양한 상황에서 발생한다.
실무 원칙은 다음과 같다.
첫째, NUMBER 컬럼 설계 시 정수부 자릿수를 충분히 확보해 두는 것이 안전하다.
둘째, INSERT INTO SELECT나 계산 결과 입력 시 사전 검증 쿼리로 위반 가능성을 확인한다.
셋째, ROUND는 소수부, 컬럼 확장은 정수부 문제 해결책임을 구분한다.
트러블슈팅 체크리스트
본 글은 Oracle Database NUMBER 정밀도 에러 ORA-01438의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.
#ORA01438 #valuelargerthanprecision #오라클에러 #NUMBER #정밀도 #precision #scale #ALTERMODIFY #ROUND #TRUNC #CAST #ORA12899 #SQL제약 #데이터타입 #DB트러블슈팅
댓글