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

ORA-01403
2026년 07월 10일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-01403 no data found 는?

ORA-01403 에러는 Oracle PL/SQL 블록 내에서 SELECT INTO 구문을 실행했을 때, 조건에 맞는 데이터가 단 하나도 존재하지 않을 경우 발생하는 예외(Exception)입니다. 일반 SQL 쿼리에서는 결과가 없어도 단순히 0건을 반환하지만, PL/SQL의 SELECT INTO는 반드시 정확히 1건의 행을 반환해야 하므로 데이터가 없으면 이 에러를 발생시킵니다. 실무에서는 배치 프로그램, 프로시저, 트리거, 패키지 등 PL/SQL을 사용하는 모든 환경에서 매우 빈번하게 마주치는 에러 중 하나입니다.


주요 발생 원인

1. SELECT INTO 구문에서 조건에 맞는 행이 없는 경우

가장 일반적인 원인으로, PL/SQL 블록 내에서 SELECT ... INTO 구문을 사용할 때 WHERE 절의 조건과 일치하는 레코드가 테이블에 존재하지 않으면 즉시 ORA-01403이 발생합니다. 이는 개발 단계에서는 테스트 데이터가 있어 정상 작동하다가, 운영 환경에서 특정 조건의 데이터가 없을 때 예기치 않게 터지는 경우가 많습니다. 특히 마스터 테이블 조회, 코드 테이블 참조, 특정 기간 데이터 집계 시 자주 발생합니다.

2. 커서(Cursor) 없이 동적 조건으로 단일 행 조회를 시도하는 경우

사용자 입력값이나 파라미터에 따라 WHERE 조건이 동적으로 바뀌는 경우, 어떤 파라미터 조합에서는 결과가 없을 수 있습니다. 예를 들어 특정 날짜 범위, 특정 부서 코드, 특정 상태값 등의 조건이 복합적으로 적용될 때 해당 조건을 만족하는 데이터가 없다면 에러가 발생합니다. 이런 경우는 예외 처리(Exception Handling)가 없으면 전체 트랜잭션이 롤백될 수도 있어 더욱 위험합니다.

3. FETCH 후 데이터 존재 여부 확인 없이 변수에 할당하는 경우

명시적 커서(Explicit Cursor)를 사용할 때 FETCH를 통해 데이터를 가져오는데, 커서가 비어 있거나(empty) %FOUND 속성 확인 없이 변수에 값을 할당하려 할 때 발생할 수 있습니다. 암묵적 커서(Implicit Cursor)의 경우에도 SELECT INTO 방식으로 작성된 코드에서 동일한 문제가 생깁니다. 이 경우는 로직 설계 단계에서 커서의 행 존재 여부를 반드시 사전에 검증하는 습관이 필요합니다.


해결 방법

해결책 1: EXCEPTION 블록으로 NO_DATA_FOUND 처리

가장 기본적이고 권장되는 방법은 PL/SQL 블록에 EXCEPTION 절을 추가하여 NO_DATA_FOUND 예외를 명시적으로 처리하는 것입니다.

DECLARE
  v_emp_name VARCHAR2(100);
  v_salary   NUMBER;
BEGIN
  -- 직원 정보를 조회하는 SELECT INTO 구문
  SELECT emp_name, salary
    INTO v_emp_name, v_salary
    FROM employees
   WHERE employee_id = 9999; -- 존재하지 않는 ID

  DBMS_OUTPUT.PUT_LINE('이름: ' || v_emp_name || ', 급여: ' || v_salary);

EXCEPTION
  WHEN NO_DATA_FOUND THEN
    -- 데이터가 없을 경우 기본값 처리 또는 로그 기록
    DBMS_OUTPUT.PUT_LINE('해당 직원 정보가 존재하지 않습니다.');
    v_emp_name := 'UNKNOWN';
    v_salary   := 0;
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('예기치 않은 오류 발생: ' || SQLERRM);
    RAISE;
END;
/

해결책 2: COUNT를 이용한 사전 존재 여부 확인

데이터 조회 전에 COUNT를 이용해 행의 존재 여부를 먼저 확인한 뒤 처리하는 방식입니다.

DECLARE
  v_count    NUMBER;
  v_emp_name VARCHAR2(100);
  v_salary   NUMBER;
  v_emp_id   NUMBER := 1001;
BEGIN
  -- 먼저 데이터 존재 여부 확인
  SELECT COUNT(*)
    INTO v_count
    FROM employees
   WHERE employee_id = v_emp_id;

  IF v_count > 0 THEN
    -- 데이터가 존재할 때만 SELECT INTO 수행
    SELECT emp_name, salary
      INTO v_emp_name, v_salary
      FROM employees
     WHERE employee_id = v_emp_id;

    DBMS_OUTPUT.PUT_LINE('이름: ' || v_emp_name || ', 급여: ' || v_salary);
  ELSE
    DBMS_OUTPUT.PUT_LINE('직원 ID ' || v_emp_id || '에 해당하는 데이터가 없습니다.');
  END IF;
END;
/

해결책 3: 커서(Cursor)를 사용하여 안전하게 처리

명시적 커서를 사용하면 데이터가 없어도 ORA-01403이 발생하지 않으며, %FOUND%NOTFOUND 속성으로 안전하게 처리할 수 있습니다.

DECLARE
  CURSOR cur_emp (p_emp_id NUMBER) IS
    SELECT emp_name, salary
      FROM employees
     WHERE employee_id = p_emp_id;

  v_emp_name VARCHAR2(100);
  v_salary   NUMBER;
BEGIN
  OPEN cur_emp(9999);
  FETCH cur_emp INTO v_emp_name, v_salary;

  IF cur_emp%FOUND THEN
    DBMS_OUTPUT.PUT_LINE('이름: ' || v_emp_name);
    DBMS_OUTPUT.PUT_LINE('급여: ' || v_salary);
  ELSE
    DBMS_OUTPUT.PUT_LINE('데이터가 존재하지 않습니다.');
  END IF;

  CLOSE cur_emp;
END;
/

해결책 4: MAX/MIN 집계 함수로 NULL 반환 유도

집계 함수(MAX, MIN 등)는 해당하는 행이 없을 경우 에러 대신 NULL을 반환하므로, 이를 활용해 ORA-01403을 피할 수 있습니다.

DECLARE
  v_max_salary NUMBER;
  v_dept_id    NUMBER := 99; -- 존재하지 않는 부서
BEGIN
  -- MAX 함수는 데이터가 없어도 NULL 반환 (에러 없음)
  SELECT MAX(salary)
    INTO v_max_salary
    FROM employees
   WHERE department_id = v_dept_id;

  IF v_max_salary IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('해당 부서에 직원이 없습니다.');
  ELSE
    DBMS_OUTPUT.PUT_LINE('최고 급여: ' || v_max_salary);
  END IF;
END;
/

예방 방법

1. 모든 SELECT INTO 구문에는 반드시 EXCEPTION 블록을 작성하는 코딩 표준 수립

팀 차원의 코딩 컨벤션으로 PL/SQL 내 SELECT INTO 구문을 사용하는 모든 곳에 NO_DATA_FOUND 예외 처리를 필수 요소로 규정해야 합니다. 코드 리뷰 체크리스트에 “SELECT INTO 사용 시 NO_DATA_FOUND 처리 여부 확인” 항목을 포함시키고, 정적 분석 도구(PL/SQL 린터 등)를 활용해 누락된 예외 처리 코드를 자동으로 검출하는 체계를 갖추는 것이 좋습니다.

2. 단일 행 조회가 보장되지 않는 경우 커서(Cursor) 또는 집계함수 사용 습관화

데이터 존재 여부가 100% 보장되지 않는 상황에서는 SELECT INTO 대신 명시적 커서나 FOR 루프 커서를 사용하는 것을 기본 원칙으로 삼아야 합니다. 또한 단일 값 조회 시에는 가능하면 NVL(MAX(컬럼명), 기본값) 패턴을 활용하면 예외 처리 코드 없이도 안전하게 NULL 또는 기본값을 받아올 수 있어 코드가 간결해집니다.


관련 에러

  • ORA-01422 (exact fetch returns more than requested number of rows): ORA-01403과 반대 상황으로, SELECT INTO 구문이 2건 이상의 행을 반환할 때 발생합니다. 두 에러는 항상 함께 고려해야 하며, 명시적 커서 사용 시 두 에러 모두 방지할 수 있습니다.
  • ORA-06512: PL/SQL 스택 트레이스 에러로, ORA-01403 발생 시 함께 출력되어 에러가 발생한 정확한 라인 번호와 오브젝트 정보를 제공합니다. 디버깅 시 이 에러와 함께 분석하면 원인 파악이 빠릅니다.
  • ORA-01001 (invalid cursor): 커서를 열지 않은 채 FETCH하거나 이미 닫힌 커서에 접근할 때 발생하며, 커서 관련 로직에서 ORA-01403과 함께 발생하는 경우가 있습니다.
DBMS 에러 코드 시리즈

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

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

댓글 남기기