PL/SQL에서 SELECT INTO 문은 특정 테이블의 한 행(Row)을 조회하여 그 결과를 변수에 직접 담을 수 있는 매우 편리한 기능입니다. 하지만 이 편리함에는 **”조회 결과는 반드시 단 하나의 행이어야 한다”**는 엄격한 규칙이 따릅니다.
ORA-01403과 ORA-01422 오류는 바로 이 규칙이 깨졌을 때, 즉 조회된 행이 0개이거나 2개 이상일 때 발생하는 문제입니다.
## ORA-01403: no data found (데이터가 없을 때)
이 오류는 SELECT INTO 문이 실행되었지만, WHERE 절의 조건을 만족하는 데이터가 단 한 건도 없을 때 발생합니다. Oracle은 이때 NO_DATA_FOUND라는 예외(Exception)를 발생시킵니다.
- 발생 시나리오: 존재하지 않는 사원번호(
EMPNO)로 사원명을 조회하는 경우
DECLARE
v_ename EMP.ENAME%TYPE;
BEGIN
-- EMPNO = 9999 인 사원은 존재하지 않음
SELECT ENAME INTO v_ename FROM EMP WHERE EMPNO = 9999;
DBMS_OUTPUT.PUT_LINE('사원명: ' || v_ename);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('오류: 해당 사원 정보를 찾을 수 없습니다.');
END;
/
해결 방안: 예외 처리 (Exception Handling)
ORA-01403은 버그나 결함이라기보다는, 데이터의 자연스러운 상태를 알려주는 신호입니다. 따라서 이 오류는 EXCEPTION 블록을 사용하여 정상적인 로직으로 처리해야 합니다.
WHEN NO_DATA_FOUND THEN구문을 사용하여 해당 예외를 잡아내고, 데이터가 없을 때 수행해야 할 작업(예: 오류 메시지 반환, 기본값 설정, 로깅)을 정의하는 것이 올바른 프로그래밍 방식입니다.
## ORA-01422: exact fetch returns more than requested number of rows (데이터가 너무 많을 때)
이 오류는 ORA-01403과 정반대의 상황으로, SELECT INTO 문이 두 건 이상의 행을 반환했을 때 발생합니다. Oracle은 하나의 변수에 여러 개의 값을 담을 수 없으므로, TOO_MANY_ROWS 예외를 발생시킵니다.
- 발생 시나리오: 여러 명의 사원이 소속된 부서 번호(
DEPTNO)로 사원명을 조회하는 경우
DECLARE
v_ename EMP.ENAME%TYPE;
BEGIN
-- DEPTNO = 10 인 사원은 여러 명 존재
SELECT ENAME INTO v_ename FROM EMP WHERE DEPTNO = 10;
DBMS_OUTPUT.PUT_LINE('사원명: ' || v_ename);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('오류: 조회된 사원이 너무 많아 한 명을 특정할 수 없습니다.');
END;
/
해결 방안: 올바른 도구 사용
ORA-01422 오류가 발생했다는 것은 애초에 SELECT INTO라는 잘못된 도구를 사용했다는 의미일 수 있습니다.
- 커서(CURSOR) 사용: 여러 건의 데이터를 처리하는 것이 목적이라면, **
CURSOR**를 사용하는 것이 정답입니다. 커서를 사용하면 결과 집합을 한 행씩 반복적으로 처리할 수 있습니다. - 쿼리 조건 구체화: 만약 정말로 단 한 건의 데이터만 필요한 상황이라면,
WHERE절에 조건을 추가하거나ROWNUM = 1과 같은 조건을 사용하여 반환되는 행이 반드시 하나가 되도록 쿼리를 수정해야 합니다.
BEGIN
-- DEPTNO = 10 인 모든 사원을 한 명씩 출력
FOR emp_rec IN (SELECT ENAME FROM EMP WHERE DEPTNO = 10) LOOP
DBMS_OUTPUT.PUT_LINE('사원명: ' || emp_rec.ename);
END LOOP;
END;
/
## 요약 및 모범 사례 ✅
SELECT INTO를 사용할 때는 항상 다음 표를 기억하세요.
| 조회 결과 | 오류 코드 | 예외(Exception) 이름 | 해결책 |
| 0 건 | ORA-01403 | NO_DATA_FOUND | EXCEPTION 블록으로 처리 |
| 1 건 | (정상) | – | – |
| 2 건 이상 | ORA-01422 | TOO_MANY_ROWS | CURSOR 사용 또는 쿼리 수정 |
”
SELECT INTO는 조회 조건이 Primary Key처럼 결과를 반드시 하나만 반환한다고 100% 확신할 수 있을 때만 사용해야 합니다. “
이 원칙을 지키고, 결과가 없거나 많을 수 있는 모든 가능성에 대해 예외 처리와 커서를 적절히 활용하는 것이 견고한 PL/SQL 코드를 작성하는 핵심입니다.