본문 바로가기
IT

ORA-01403 no data found — PL/SQL SELECT INTO 결과 없음 에러 원인·해결·예방

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

ORA-01403 no data found — PL/SQL SELECT INTO 결과 없음 에러 원인·해결·예방

Oracle PL/SQL에서 SELECT INTO 구문을 사용하다 보면 ORA-01403: no data found 에러를 자주 만난다. 조회 결과가 0건일 때 PL/SQL이 예외를 던지면서 발생하는 에러로, SQL 단독 실행에서는 발생하지 않고 PL/SQL 블록 안에서만 일어난다는 점이 헷갈리기 쉬운 부분이다.

 

본 글은 ORA-01403의 정확한 의미와 자주 발생하는 6가지 케이스, NO_DATA_FOUND 예외 처리·집계함수 변환·CURSOR·BULK COLLECT 등 5가지 회피 패턴, 유사 에러 ORA-01422·ORA-06502·ORA-06512와의 관계까지 정리한 트러블슈팅 자료다.

 

ORA-01403

이 글의 구성

 

01에러 메시지와 카테고리
02발생 원인 6가지
03재현 시나리오와 코드 예제
04회피 패턴 5가지
05유사 에러 비교 (01422·06502·06512)
Q&A자주 묻는 질문 5가지

01 에러 메시지와 카테고리

ORA-01403은 PL/SQL의 SELECT INTO 결과가 0건일 때, 또는 Associative Array의 미존재 키를 참조할 때 발생하는 에러다. SQLCODE 100에 매핑된 사전 정의 예외 NO_DATA_FOUND와 같다.

항목 내용
에러 코드 ORA-01403
영문 메시지 no data found
SQLCODE 100
사전 정의 예외 NO_DATA_FOUND
Cause (공식) No row was returned from a SELECT INTO statement, or no rows remain in a cursor, or a referenced row in a PL/SQL table was undefined.
Action (공식) SELECT INTO 결과가 0건일 가능성을 처리하거나 예외 처리 구문(EXCEPTION WHEN NO_DATA_FOUND THEN)을 추가
발생 영역 PL/SQL 블록 (Procedure·Function·Trigger·Anonymous Block)

핵심 관찰 — SQL과 PL/SQL의 차이

동일한 0건 결과라도 SQL 단독 SELECT는 ORA-01403을 던지지 않는다. 단순히 "rows selected" 0건으로 정상 종료된다. ORA-01403은 PL/SQL의 SELECT INTO처럼 반드시 변수에 값을 대입해야 하는 구문에서만 발생한다. 디버깅 시 이 차이를 명확히 인지하는 것이 중요하다.


02 발생 원인 6가지

원인 1 — SELECT INTO 결과 0건

가장 흔한 케이스다. WHERE 조건에 매칭되는 행이 없을 때 SELECT INTO는 변수에 값을 대입할 수 없어 NO_DATA_FOUND 예외를 던진다.

원인 2 — Associative Array 미존재 키 접근

Index-by Table(Associative Array)에서 존재하지 않는 키를 참조하면 ORA-01403이 발생한다. .EXISTS() 메서드로 사전 확인이 필요하다.

원인 3 — 명시적 커서 FETCH 후 NOTFOUND 확인 누락

CURSOR를 OPEN하고 FETCH한 후 %NOTFOUND 체크 없이 데이터를 사용하면, 마지막 행 이후에도 FETCH를 시도해 ORA-01403이 발생할 수 있다.

원인 4 — 트리거 본문 내 SELECT INTO

트리거에서 마스터 테이블 조회 시 결과가 0건이면 트리거 실행이 실패하고 원래 DML도 롤백된다. 자식 테이블 처리·검증 트리거에서 자주 발생한다.

원인 5 — Function 내부 SELECT INTO

PL/SQL Function 안의 SELECT INTO에서 NO_DATA_FOUND가 발생하면 Function을 호출한 SQL 문까지 예외가 전파되어 전체 쿼리가 실패한다.

원인 6 — 데이터 보정·이관 후 누락 행

데이터 마이그레이션·정리 작업 후 기존 PL/SQL 로직이 가정하던 행이 사라지면, 평소 잘 작동하던 코드에서 갑자기 ORA-01403이 발생한다.


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

원인 1 — SELECT INTO 0건

-- ✗ id=999인 행이 없으면 NO_DATA_FOUND
DECLARE
  v_name VARCHAR2(50);
BEGIN
  SELECT name INTO v_name
    FROM emp
   WHERE id = 999;
  -- ORA-01403: no data found
END;
/

원인 2 — Associative Array 미존재 키

DECLARE
  TYPE t_arr IS TABLE OF VARCHAR2(50) INDEX BY VARCHAR2(10);
  v_arr t_arr;
  v_val VARCHAR2(50);
BEGIN
  v_arr('A') := 'Apple';
  -- ✗ 'X' 키 없음 → ORA-01403
  v_val := v_arr('X');

  -- ✓ EXISTS 체크 후 접근
  IF v_arr.EXISTS('X') THEN
    v_val := v_arr('X');
  END IF;
END;
/

원인 3 — 커서 FETCH 후 NOTFOUND 누락

DECLARE
  CURSOR c_emp IS SELECT name FROM emp;
  v_name VARCHAR2(50);
BEGIN
  OPEN c_emp;
  LOOP
    FETCH c_emp INTO v_name;
    -- ✓ 반드시 NOTFOUND 체크
    EXIT WHEN c_emp%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_name);
  END LOOP;
  CLOSE c_emp;
END;
/

원인 5 — Function 내부에서 SELECT INTO 전파

CREATE OR REPLACE FUNCTION get_dept_name(p_id NUMBER)
  RETURN VARCHAR2 IS
  v_name VARCHAR2(100);
BEGIN
  SELECT name INTO v_name FROM dept WHERE id = p_id;
  RETURN v_name;
END;
/

-- ✗ Function이 NO_DATA_FOUND 던지면 SQL 전체 실패
SELECT emp.id, get_dept_name(emp.dept_id) FROM emp;
-- ORA-01403 (특정 dept_id가 dept 테이블에 없으면)

04 회피 패턴 5가지

ORA-01403은 적절한 회피 패턴으로 사전 방어할 수 있다.

패턴 1 — NO_DATA_FOUND 예외 처리

DECLARE
  v_name VARCHAR2(50);
BEGIN
  SELECT name INTO v_name FROM emp WHERE id = 999;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    v_name := '(unknown)';  -- ✓ 기본값 설정
END;
/

패턴 2 — 집계함수로 변환 (항상 1행 반환)

-- MAX·MIN·COUNT·SUM·AVG는 결과 0건이어도 NULL 반환 → ORA-01403 미발생
SELECT MAX(name) INTO v_name FROM emp WHERE id = 999;
-- v_name이 NULL이 될 뿐, 예외는 발생하지 않음

패턴 3 — CURSOR + FETCH + NOTFOUND 체크

CURSOR 기반 접근은 0건 상황을 자연스럽게 처리한다. 위 원인 3 예시 코드 참고.

패턴 4 — COUNT(*)로 사전 검증 후 분기

DECLARE
  v_cnt NUMBER;
  v_name VARCHAR2(50);
BEGIN
  SELECT COUNT(*) INTO v_cnt FROM emp WHERE id = 999;
  IF v_cnt > 0 THEN
    SELECT name INTO v_name FROM emp WHERE id = 999;
  END IF;
END;
/

패턴 5 — BULK COLLECT INTO (0건 안전)

DECLARE
  TYPE t_list IS TABLE OF VARCHAR2(50);
  v_names t_list;
BEGIN
  -- ✓ BULK COLLECT는 0건이어도 ORA-01403 미발생
  SELECT name BULK COLLECT INTO v_names
    FROM emp WHERE dept_id = 999;
  -- v_names는 빈 컬렉션 (COUNT=0)
  IF v_names.COUNT = 0 THEN
    DBMS_OUTPUT.PUT_LINE('no rows');
  END IF;
END;
/

05 유사 에러 비교 (01422·06502·06512)

에러 의미 관계
ORA-01403 no data found (0행) SELECT INTO 결과 0건
ORA-01422 exact fetch returns more than requested (다중 행) 01403의 정반대 — 2행 이상
ORA-06502 numeric or value error (PL/SQL 값 오류) 별개이지만 같은 스택에 동반될 수 있음
ORA-06512 at line X (예외 발생 PL/SQL 위치) 원인이 아닌 위치 표시 — 함께 출력됨

기억법: 01403=비어있음, 01422=초과(2행+), 06502=값/타입 오류, 06512=위치 표시.


06 자주 묻는 질문 5가지

Q1SQL Developer에서 SELECT만 실행하면 ORA-01403이 안 나는데 왜인가

SQL 단독 실행은 0행이 정상 결과다. ORA-01403은 PL/SQL의 SELECT INTO처럼 변수에 반드시 값을 대입해야 하는 구문에서만 발생한다. 같은 쿼리라도 PL/SQL 블록 안에서 INTO 절을 사용하면 0건이 예외로 처리된다.

Q2NO_DATA_FOUND 예외를 그냥 무시해도 되나

권장하지 않는다. EXCEPTION WHEN NO_DATA_FOUND THEN NULL;처럼 빈 처리를 두면 0건 상황이 조용히 무시되어 디버깅이 어려워진다. 기본값을 설정하거나 로그를 남기는 처리를 함께 두는 것이 안전하다.

Q3SELECT MAX 변환이 항상 안전한 회피책인가

대부분의 단일 행 조회 회피에 사용 가능하다. MAX·MIN·SUM·AVG·COUNT 같은 집계함수는 결과 행이 0건이어도 NULL을 반환하므로 ORA-01403이 발생하지 않는다. 다만 NULL 값을 받았을 때 후속 로직에서 별도 처리가 필요할 수 있다.

Q4ORA-01403과 ORA-06512가 함께 표시되는 이유는

ORA-06512는 예외가 발생한 PL/SQL의 라인 위치를 알려주는 메시지다. ORA-01403이 원인 에러이고 ORA-06512는 그 위치를 따라가는 추적 메시지다. 디버깅 시 ORA-06512의 라인 번호로 문제가 발생한 SELECT INTO 위치를 빠르게 찾을 수 있다.

Q5BULK COLLECT가 0건에 안전하다면 왜 항상 사용하지 않나

BULK COLLECT는 대량 처리에 효과적이지만, 단일 값 조회에는 컬렉션 변수와 인덱스 접근이 필요해 코드가 복잡해진다. 또한 매우 큰 결과 셋을 BULK COLLECT로 한 번에 가져오면 PGA 메모리를 많이 사용하므로 LIMIT 절로 청크 단위 처리가 권장된다. 단일 행 조회에는 예외 처리 또는 집계함수 변환이 더 단순하다.


07 결론

ORA-01403은 PL/SQL의 SELECT INTO 결과가 0건일 때 발생하는 가장 흔한 예외 중 하나다. SQL 단독 실행과 PL/SQL의 차이를 이해하고, 사전 정의 예외 NO_DATA_FOUND의 동작 방식을 익히면 빠르게 해결할 수 있다.

 

실무 적용 원칙은 다음과 같다.

 

첫째, 단일 값 조회는 EXCEPTION WHEN NO_DATA_FOUND 처리 또는 MAX·MIN 집계함수 변환을 표준으로 한다.

둘째, 다중 행 조회는 CURSOR + FETCH + NOTFOUND 패턴 또는 BULK COLLECT를 사용해 0건 상황을 자연스럽게 흡수한다.

셋째, 디버깅 시 ORA-06512가 함께 표시되면 그 라인 번호를 따라가 문제가 된 SELECT INTO 위치를 빠르게 좁힌다.

ORA-01403은 PL/SQL이 0건을 정상 결과로 받아들이지 못해 던지는 예외다. NO_DATA_FOUND·집계함수·CURSOR·BULK COLLECT 중 상황에 맞는 패턴을 적용하면 안전하다.

 

— SQL 단독은 0건 정상, PL/SQL의 SELECT INTO만 예외 발생

트러블슈팅 체크리스트

 

01SQL 단독과 PL/SQL SELECT INTO의 차이를 인식한다.
02ORA-06512 라인 번호로 문제 위치를 좁힌다.
03EXCEPTION WHEN NO_DATA_FOUND 처리로 기본값을 설정한다.
04단일 값 조회는 MAX·MIN 집계함수로 변환 검토한다.
05다중 행 조회는 CURSOR + FETCH + NOTFOUND 패턴을 사용한다.
06Associative Array 접근 전 EXISTS 메서드로 키를 확인한다.
07대량 조회는 BULK COLLECT + LIMIT로 안전하게 처리한다.

본 글은 Oracle Database PL/SQL 예외 ORA-01403의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.

 

#ORA01403 #nodatafound #오라클에러 #PLSQL #SELECTINTO #NO_DATA_FOUND #예외처리 #CURSOR #BULKCOLLECT #ORA01422 #ORA06502 #ORA06512 #PLSQL함수 #PLSQL트리거 #DB트러블슈팅

반응형

댓글