ORA-01843은 오라클이 문자열을 날짜로 변환할 때 월(month) 값이 유효하지 않다고 판단할 때 발생한다. 1~12 범위를 벗어나거나, MON·MONTH 마스크와 세션 언어가 맞지 않아 월 이름을 인식하지 못할 때 던져진다. ORA-01861이 "구조가 안 맞다"고 알려주는 1차 방어선이라면, ORA-01843은 "값이 잘못됐다"고 알려주는 2차 방어선이다. 한국어 세션이 기본인 국내 환경에서는 영문 약어 MON 마스크 사용 시 매우 흔히 마주친다. 본 글은 ORA-01843의 정확한 의미, 다섯 가지 원인, 진단 흐름, 그리고 NLS에 의존하지 않는 견고한 해결 패턴까지 정리한다.

주요 원인 / MM 13 이상, MON/MONTH + 언어 불일치, NLS 암시적 변환, 구분자 위치 혼동, NLS_TERRITORY 영향
근본 해법 / TO_DATE 3번째 인자
NLS_DATE_LANGUAGE=AMERICAN, ANSI DATE '2026-05-15' 리터럴목차
ORA-01843은 값(value) 검증에 걸린 에러다. ORA-01861이 "글자 수·구분자 자체가 안 맞다"는 구조 검증에 걸리는 반면, ORA-01843은 구조는 통과했지만 안에 들어 있는 월 값이 잘못된 경우다. 예를 들어
'2026-13-01'과 'YYYY-MM-DD' 조합은 구조는 맞지만 13월이라는 값이 부적합해서 ORA-01843이 발생한다.1. ORA-01843이 던져지는 두 가지 경로
ORA-01843이 발생하는 경로는 크게 두 가지다.
경로 A / 숫자 월이 범위를 벗어남
MM, MON이 아닌 숫자 마스크에서 1~12 밖의 값이 들어왔을 때다. 13, 0, 99 같은 명백한 오류가 여기 해당한다.
경로 B / MON·MONTH 마스크가 세션 언어와 불일치
MON, MONTH 마스크는 텍스트 기반이고, 그 텍스트는 세션의 NLS_DATE_LANGUAGE 설정을 따른다. 한국어 세션은 1월, 2월을 기대하고, 영어 세션은 JAN, FEB를 기대한다. 입력 문자열과 세션 언어가 어긋나면 오라클은 월 이름을 인식하지 못해 ORA-01843을 던진다.
국내 운영 환경에서 흔히 마주치는 패턴은 경로 B다. 시스템 NLS가 KOREAN으로 설정돼 있는데 데이터나 코드는 영어 약어를 사용하는 경우가 많기 때문이다.
2. 발생 원인 다섯 가지
원인 1 / 월 값 범위 초과
가장 단순한 경우다. 입력 데이터 자체가 잘못된 월 값을 담고 있다.
-- 13월 → ORA-01843
SELECT TO_DATE('2026-13-01', 'YYYY-MM-DD') FROM dual;
-- 00월 → ORA-01843
SELECT TO_DATE('2026-00-15', 'YYYY-MM-DD') FROM dual;
대부분은 데이터 정제 단계에서 걸러야 할 사례다. ETL 파이프라인이나 입력 폼 검증에서 1~12 범위 체크를 추가하면 사전 차단된다.
원인 2 / MON·MONTH 마스크와 NLS_DATE_LANGUAGE 불일치
국내 환경에서 가장 빈번한 원인이다. 한국어 세션에서 영문 약어를 파싱하려고 하면 즉시 실패한다.
-- 세션이 한국어인 상태
ALTER SESSION SET NLS_DATE_LANGUAGE = 'KOREAN';
-- 한국어 세션은 'JAN'을 모름 → ORA-01843
SELECT TO_DATE('15-JAN-26', 'DD-MON-YY') FROM dual;
-- 한국어 세션은 '1월'을 기대 → 성공
SELECT TO_DATE('15-1월 -26', 'DD-MON-YY') FROM dual;
반대 방향도 마찬가지다. 영어 세션에서 한국어 월 이름을 파싱하면 같은 에러가 발생한다.
원인 3 / NLS 암시적 변환 차이
문자열을 직접 DATE 컬럼과 비교하거나 INSERT하면 오라클은 세션 NLS_DATE_FORMAT을 사용해 자동으로 TO_DATE를 호출한다. 이때 적용되는 마스크가 DD-MON-RR처럼 MON을 포함한 형식이면, 입력 문자열이 영문 약어를 갖고 있어야 한다.
-- 세션 NLS_DATE_FORMAT이 'DD-MON-RR'인 환경
INSERT INTO emp(hire_date) VALUES ('15-05-2026');
-- 오라클: TO_DATE('15-05-2026', 'DD-MON-RR') → MON 자리에 '05' → ORA-01843
원인 4 / 구분자 위치 혼동
마스크와 입력의 구분자 위치는 같지만, 어느 자리가 일·월·연도인지 해석이 어긋날 때 발생한다.
-- 입력은 DD-MM-YYYY인데 마스크는 MM-DD-YYYY
SELECT TO_DATE('15-05-2026', 'MM-DD-YYYY') FROM dual;
-- 오라클: 월=15 → ORA-01843
구조 검사(ORA-01861)는 통과한다. 길이도 같고 구분자 위치도 같기 때문이다. 하지만 첫 번째 숫자 15가 월로 해석되면서 값 검사에서 걸린다.
원인 5 / NLS_TERRITORY 변경 영향
NLS_TERRITORY를 바꾸면 그에 따라 NLS_DATE_FORMAT 기본값도 함께 바뀐다. KOREA → RR/MM/DD, AMERICA → DD-MON-RR, JAPAN → RR-MM-DD처럼 영토마다 다르다. 같은 데이터를 다른 영토 세션에서 처리하면 형식이 어긋난다.
-- TERRITORY 변경 시 NLS_DATE_FORMAT도 자동 변경
ALTER SESSION SET NLS_TERRITORY = 'AMERICA';
-- 이제 기본 마스크는 DD-MON-RR
SELECT TO_DATE('15/05/2026') FROM dual;
-- DD-MON-RR로 해석 시도 → MON 자리 '05' → ORA-01843
3. 재현 시나리오 — 환경 의존 실패
다음 SQL은 세션 언어에 따라 결과가 갈린다.
-- 케이스 A: 영어 세션
ALTER SESSION SET NLS_DATE_LANGUAGE = 'AMERICAN';
SELECT TO_DATE('15-JAN-26', 'DD-MON-YY') FROM dual;
-- 성공: 2026-01-15
-- 케이스 B: 한국어 세션
ALTER SESSION SET NLS_DATE_LANGUAGE = 'KOREAN';
SELECT TO_DATE('15-JAN-26', 'DD-MON-YY') FROM dual;
-- ORA-01843
NLS 상태는 다음 쿼리로 확인한다.
-- 현재 세션 NLS_DATE_LANGUAGE
SELECT parameter, value
FROM nls_session_parameters
WHERE parameter IN ('NLS_DATE_FORMAT',
'NLS_DATE_LANGUAGE',
'NLS_TERRITORY');
-- 사용 가능한 언어 값 조회
SELECT value
FROM v$nls_valid_values
WHERE parameter = 'LANGUAGE'
ORDER BY value;
4. 해결 방법 — 세 가지 패턴
패턴 A / TO_DATE 3번째 인자로 언어 강제
MON·MONTH 마스크를 꼭 써야 한다면 TO_DATE의 세 번째 인자에 NLS 옵션을 명시한다. 세션 NLS와 무관하게 항상 같은 동작이 보장된다.
-- 세션 NLS와 무관하게 영어 월 이름 파싱
SELECT TO_DATE('15-JAN-26', 'DD-MON-YY',
'NLS_DATE_LANGUAGE=AMERICAN') FROM dual;
-- 한국어 월 이름 파싱
SELECT TO_DATE('15-1월 -26', 'DD-MON-YY',
'NLS_DATE_LANGUAGE=KOREAN') FROM dual;
패턴 B / MON 대신 MM 사용
월을 약어가 아닌 숫자로 표현할 수 있다면 MM 마스크가 가장 안전하다. 언어 의존이 완전히 사라진다.
-- 숫자 월 → NLS 영향 없음
SELECT TO_DATE('2026-05-15', 'YYYY-MM-DD') FROM dual;
SELECT TO_DATE('15/05/2026', 'DD/MM/YYYY') FROM dual;
패턴 C / ANSI DATE 리터럴
상수 값이면 ANSI 표준 DATE 리터럴이 가장 견고하다. NLS·언어·영토 어느 것에도 영향받지 않는다.
-- ANSI DATE 리터럴 (NLS 무관)
SELECT DATE '2026-05-15' FROM dual;
-- WHERE 절에도 사용 가능
SELECT * FROM emp
WHERE hire_date >= DATE '2026-01-01'
AND hire_date < DATE '2027-01-01';
패턴 D / 애플리케이션 바인드 변수
자바·파이썬·.NET 같은 애플리케이션에서는 문자열로 넘기지 말고 드라이버의 Date/Timestamp 타입으로 바인딩한다. 드라이버가 직접 DATE 타입으로 전송하므로 NLS 의존이 완전히 사라진다.
// Java JDBC 예시
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO emp(emp_id, hire_date) VALUES (?, ?)");
pstmt.setInt(1, 1001);
pstmt.setDate(2, java.sql.Date.valueOf("2026-05-15"));
pstmt.executeUpdate();
5. 인접 에러와의 구분
ORA-01843은 형제 격 에러가 여럿 있다. 메시지는 비슷해도 검사 단계가 다르다.
| 에러 코드 | 검사 대상 | 전형적 입력 |
|---|---|---|
| ORA-01843 | 월 값 범위·이름 | '2026-13-01' 또는 한국어 세션에 'JAN' |
| ORA-01861 | 구조 불일치 | '2026/05/15' + 'YYYY-MM-DD' |
| ORA-01847 | 일 값이 월 범위 초과 | '2026-02-31' |
| ORA-01839 | 월에 대한 일 부적합 | 2025-02-29 같은 비윤년 2/29 |
| ORA-01830 | 마스크가 리터럴보다 짧음 | '2026-05-15 14:30' + 'YYYY-MM-DD' |
| ORA-01840 | 리터럴이 마스크보다 짧음 | '2026-5' + 'YYYY-MM-DD' |
이 그룹의 에러는 모두 같은 해법 패턴을 공유한다 ━ TO_DATE를 명시하고, 마스크와 리터럴을 정확히 맞추고, NLS·언어 의존을 제거하고, 가능하면 ANSI 리터럴이나 바인드 변수로 전환한다.
TO_DATE의 세 번째 인자에
'NLS_DATE_LANGUAGE=AMERICAN'을 명시하면 세션 NLS와 무관하게 영어 월 이름을 파싱할 수 있다. 함수 호출마다 추가해야 해 번거롭지만 가장 안전한 방법이다.Q2. NLS_DATE_LANGUAGE 값 목록은 어디서 확인하나요?
SELECT value FROM v$nls_valid_values WHERE parameter='LANGUAGE'로 조회한다. AMERICAN, KOREAN, JAPANESE, SIMPLIFIED CHINESE, GERMAN, FRENCH 등 70여 종이 등록돼 있다.Q3. 같은 SQL이 어제는 됐는데 오늘 ORA-01843이 발생합니다.
세션 NLS_DATE_LANGUAGE 또는 NLS_TERRITORY가 바뀌었을 가능성이 가장 높다. 클라이언트 OS 로케일 변경, JDBC URL 옵션 변경, 커넥션 풀 init SQL 변경이 흔한 원인이다. NLS_SESSION_PARAMETERS를 비교하면 즉시 드러난다.
Q4. 데이터 적재 시 1~12 범위 검증은 어디서 하는 게 좋나요?
1차는 애플리케이션 입력 검증, 2차는 DB 레벨 CHECK 제약 또는 트리거다. CHECK 제약을 두면 잘못된 값이 DATE 컬럼이 아니라 NUMBER 컬럼으로 들어올 때도 차단된다. 다만 DATE 컬럼은 오라클이 자동으로 1~12 검증을 하므로, CHECK는 별도 월 컬럼이 있을 때만 의미가 있다.
Q5. 23ai에서도 같은 동작인가요?
ORA-01843의 메시지와 동작은 11g부터 23ai까지 동일하다. 19.4~19.8 버전에서 일부 패치 회귀로 일시적 오작동 사례가 있었으나 19.9 이후 안정화됐다. 클라우드 환경(ATP·ADW)에서도 동일하게 동작한다.
6. 예방 체크리스트와 결론
ORA-01843은 마스크 선택과 NLS 명시화로 거의 100% 차단할 수 있다. 새 쿼리·새 모듈·새 데이터 파이프라인을 만들 때 다음 항목을 점검한다.
- ✓가능한 한 MON·MONTH 대신 MM 숫자 마스크 사용 (언어 의존 제거)
- ✓MON·MONTH 사용 시 TO_DATE 3번째 인자로
NLS_DATE_LANGUAGE명시 - ✓모든 문자열 → 날짜 변환에 TO_DATE 명시 (암시적 변환 차단)
- ✓상수 값은 ANSI
DATE 'YYYY-MM-DD'리터럴 사용 - ✓커넥션 풀 초기 SQL에서
NLS_DATE_LANGUAGE·NLS_DATE_FORMAT명시 - ✓애플리케이션은 Date·Timestamp 타입으로 바인딩 (문자열 금지)
- ✓ETL 파이프라인에 월 값 1~12 검증 단계 포함
- ✓운영·개발·테스트 환경의 NLS_SESSION_PARAMETERS 동기화
ORA-01843은 단순히 "월이 13이다"라는 명백한 입력 오류뿐 아니라, NLS_DATE_LANGUAGE라는 보이지 않는 세션 상태에 의존하는 코드를 드러내는 경고다. 한국어 환경이 기본인 국내 운영에서는 영문 약어 MON 마스크가 위험 신호가 된다. 해법은 단순하다 ━ MM을 쓰거나, TO_DATE 3번째 인자로 언어를 강제하거나, ANSI 리터럴로 전환한다. 세 가지 중 하나만 일관되게 적용해도 ORA-01843은 다시 만날 일이 거의 없는 에러가 된다.
#ORA01843 #notavalidmonth #오라클에러 #NLSDATELANGUAGE #NLS #MON #MONTH #TO_DATE #날짜형식 #한국어세션 #DATE리터럴 #ORA01861 #ORA01847 #ORA01839 #SQL날짜
'IT' 카테고리의 다른 글
| 데이터 거버넌스가 뭐야 — DAMA-DMBOK·데이터 품질·소유권·Lineage·데이터 메시 완전 정리 (0) | 2026.05.19 |
|---|---|
| ORA-06550 PL/SQL compilation error — 컴파일 오류 원인·해결·예방 완전 정리 (0) | 2026.05.19 |
| Apache Iceberg가 뭐야 — 오픈 테이블 포맷·데이터 레이크하우스·스키마 진화·시간 여행 완전 정리 (0) | 2026.05.18 |
| ORA-06512 at line N — PL/SQL 스택 트레이스 에러 원인·해결·예방 완전 정리 (0) | 2026.05.18 |
| ORA-00904 invalid identifier — 부적합한 식별자·컬럼명 오타 에러 원인·해결·예방 완전 정리 (0) | 2026.05.18 |
댓글