2026년 07월 11일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-01405 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-01405 fetched column value is NULL 는?
ORA-01405 에러는 ProC, ProCOBOL 또는 OCI(Oracle Call Interface) 같은 호스트 언어 환경에서 커서(Cursor)로 데이터를 FETCH할 때, 가져온 컬럼 값이 NULL인 경우 발생합니다. 이는 NULL 값을 받을 수 있는 인디케이터 변수(Indicator Variable)를 선언하지 않았거나, FETCH된 값이 NULL임을 처리하는 로직이 없을 때 주로 발생합니다. 단순한 SQL*Plus 환경이 아닌, 임베디드 SQL 또는 OCI 기반 애플리케이션에서 자주 목격되는 에러입니다.
주요 발생 원인
1. 인디케이터 변수(Indicator Variable) 미사용
Pro*C 또는 OCI 환경에서 NULL 값이 포함될 수 있는 컬럼을 FETCH할 때, 인디케이터 변수를 선언하지 않으면 Oracle은 NULL 값을 호스트 변수에 저장할 수 없어 ORA-01405를 발생시킵니다. 인디케이터 변수는 호스트 변수와 쌍을 이루어 선언되어야 하며, NULL 여부를 감지하는 역할을 합니다.
2. FETCH 대상 컬럼에 NOT NULL 제약 미적용 또는 데이터 품질 문제
테이블 설계 시 해당 컬럼에 NOT NULL 제약 조건이 없고, 실제 데이터 중 일부가 NULL로 입력된 경우 애플리케이션 레벨에서 예상치 못한 NULL FETCH가 발생합니다. 특히 레거시 시스템이나 대량 데이터 이행(Migration) 이후에 데이터 품질이 보장되지 않아 이 에러가 빈번하게 나타납니다.
3. SELECT 절에서 NULL을 반환하는 표현식 사용
집계 함수(SUM, AVG 등)나 스칼라 서브쿼리(Scalar Subquery)가 데이터 없음으로 인해 NULL을 반환하거나, 조인 결과에서 매칭 행이 없어 NULL이 발생하는 경우입니다. 이런 경우 개발자가 쿼리 결과에 NULL이 포함될 수 있다는 사실을 간과하고 인디케이터 변수나 NVL 처리 없이 FETCH를 시도할 때 에러가 발생합니다.
해결 방법
해결책 1: 인디케이터 변수 선언 및 사용 (Pro*C 환경)
Pro*C 코드에서 NULL 가능성이 있는 컬럼에 대해 반드시 인디케이터 변수를 함께 선언하고, FETCH 이후 인디케이터 변수 값을 확인하여 NULL 여부를 처리합니다.
-- Pro*C 예제 (개념적 SQL 표현)
-- 호스트 변수와 인디케이터 변수 선언
EXEC SQL BEGIN DECLARE SECTION;
char emp_name[50];
short emp_name_ind; /* 인디케이터 변수: -1이면 NULL */
double salary;
short salary_ind; /* 인디케이터 변수 */
EXEC SQL END DECLARE SECTION;
-- FETCH 시 인디케이터 변수와 함께 사용
EXEC SQL FETCH emp_cursor
INTO :emp_name :emp_name_ind,
:salary :salary_ind;
-- FETCH 후 NULL 체크 처리 (C 코드 내)
-- if (salary_ind == -1) { salary = 0; } /* NULL이면 0으로 대체 */
해결책 2: NVL 또는 COALESCE 함수로 NULL 치환
SQL 쿼리 자체에서 NULL이 반환되지 않도록 NVL 또는 COALESCE 함수를 사용하여 NULL을 기본값으로 대체하는 방법입니다. 이는 인디케이터 변수 없이도 안전하게 FETCH할 수 있게 해주는 가장 간단한 해결책입니다.
-- 문제가 되는 쿼리 (SALARY가 NULL일 수 있음)
SELECT EMPLOYEE_ID, FIRST_NAME, SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 10;
-- 해결: NVL로 NULL을 기본값으로 치환
SELECT EMPLOYEE_ID,
NVL(FIRST_NAME, 'UNKNOWN') AS FIRST_NAME,
NVL(SALARY, 0) AS SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 10;
-- COALESCE를 이용한 다중 대체값 처리
SELECT EMPLOYEE_ID,
COALESCE(FIRST_NAME, LAST_NAME, 'NO NAME') AS EMP_NAME,
COALESCE(SALARY, COMMISSION_PCT * 1000, 0) AS EFFECTIVE_PAY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 10;
해결책 3: 집계 함수 또는 스칼라 서브쿼리의 NULL 처리
집계 함수나 서브쿼리가 NULL을 반환할 경우를 대비해 NVL을 감싸는 패턴을 사용합니다.
-- 집계 함수에서 NULL이 반환되는 경우 (데이터가 없을 때 SUM은 NULL 반환)
-- 문제 쿼리
SELECT DEPARTMENT_ID, SUM(SALARY) AS TOTAL_SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 999 -- 존재하지 않는 부서
GROUP BY DEPARTMENT_ID;
-- 해결: NVL로 NULL 처리
SELECT DEPARTMENT_ID,
NVL(SUM(SALARY), 0) AS TOTAL_SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 999
GROUP BY DEPARTMENT_ID;
-- 스칼라 서브쿼리에서 NULL 반환 방지
SELECT E.EMPLOYEE_ID,
E.FIRST_NAME,
NVL(
(SELECT SUM(S.AMOUNT)
FROM SALES S
WHERE S.EMP_ID = E.EMPLOYEE_ID),
0
) AS TOTAL_SALES
FROM EMPLOYEES E
WHERE E.DEPARTMENT_ID = 80;
-- OUTER JOIN으로 NULL 처리 후 NVL 적용
SELECT E.EMPLOYEE_ID,
E.FIRST_NAME,
NVL(D.DEPARTMENT_NAME, 'UNASSIGNED') AS DEPT_NAME
FROM EMPLOYEES E
LEFT OUTER JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
해결책 4: FETCH 전 NULL 데이터 사전 필터링
가능하다면 WHERE 절에 IS NOT NULL 조건을 추가하여 NULL 데이터를 FETCH 대상에서 제외하는 방법입니다.
-- NULL 데이터를 미리 필터링
SELECT EMPLOYEE_ID, FIRST_NAME, SALARY, COMMISSION_PCT
FROM EMPLOYEES
WHERE SALARY IS NOT NULL
AND COMMISSION_PCT IS NOT NULL
AND DEPARTMENT_ID = 80
ORDER BY EMPLOYEE_ID;
-- NULL 포함 여부 사전 확인 쿼리 (운영 중 데이터 점검용)
SELECT COUNT(*) AS TOTAL_ROWS,
COUNT(SALARY) AS NON_NULL_SALARY,
COUNT(*) - COUNT(SALARY) AS NULL_SALARY_COUNT
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 80;
예방 방법
1. 모든 호스트 변수에 인디케이터 변수를 기본으로 쌍으로 선언하는 코딩 표준 수립
ProC, ProCOBOL, OCI 기반 애플리케이션을 개발할 때, NULL이 절대 발생하지 않는다고 확신하는 컬럼이더라도 반드시 인디케이터 변수를 쌍으로 선언하는 팀 코딩 표준을 정립해야 합니다. 이는 데이터 변경이나 비즈니스 요건 변경으로 인해 추후 NULL이 유입될 가능성을 원천 차단하는 방어적 프로그래밍(Defensive Programming) 방식으로, 코드 리뷰 체크리스트에 반드시 포함시켜야 합니다.
-- 테이블 설계 단계에서 NOT NULL 제약 명확히 정의
CREATE TABLE EMPLOYEES_SAFE (
EMPLOYEE_ID NUMBER(6) NOT NULL,
FIRST_NAME VARCHAR2(50) NOT NULL, -- NOT NULL 명시
SALARY NUMBER(8,2) DEFAULT 0 NOT NULL, -- DEFAULT + NOT NULL
DEPT_ID NUMBER(4) NOT NULL,
CONSTRAINT PK_EMP_SAFE PRIMARY KEY (EMPLOYEE_ID)
);
2. SELECT 쿼리 작성 시 NVL/COALESCE를 표준화하여 NULL-Safe 쿼리 작성 원칙 도입
애플리케이션에서 사용하는 모든 SELECT 쿼리의 코드 리뷰 시, NULL 가능성이 있는 컬럼에 대해 NVL 또는 COALESCE 적용 여부를 필수 확인 항목으로 지정합니다. 특히 집계 함수, OUTER JOIN, 스칼라 서브쿼리를 사용하는 쿼리는 항상 NULL 반환 가능성을 전제하고 방어 코드를 작성하는 관행을 팀 문화로 정착시켜야 합니다.
관련 에러
- ORA-01400: NULL을 NOT NULL 컬럼에 INSERT하려 할 때 발생. ORA-01405와 반대 방향의 NULL 관련 에러입니다.
- ORA-01403: NO DATA FOUND. FETCH 시 데이터가 전혀 없는 경우로, ORA-01405와 함께 커서 처리 시 반드시 핸들링해야 하는 에러입니다.
- ORA-06502: PL/SQL numeric or value error. PL/SQL 환경에서 NULL을 NOT NULL 변수에 대입하려 할 때 발생할 수 있으며, ORA-01405와 유사한 맥락의 에러입니다.
- ORA-01422: exact fetch returns more than requested number of rows. SELECT INTO 구문에서 여러 행이 반환될 때 발생하며, 커서 관련 에러로 ORA-01405와 함께 자주 언급됩니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.