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

ORA-06502
2026년 08월 28일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-06502 PL/SQL: numeric or value error 는?

ORA-06502는 PL/SQL 코드 실행 중 숫자 또는 값 관련 오류가 발생했을 때 나타나는 에러입니다. 주로 변수에 허용된 크기보다 큰 값을 할당하거나, 숫자가 아닌 문자열을 숫자형 변수에 대입하려 할 때, 또는 NULL 값을 NOT NULL 제약이 걸린 변수에 넣으려 할 때 발생합니다. 이 에러는 단독으로 발생하기도 하지만, 하위 에러 메시지(ORA-06502: … string buffer too small 등)와 함께 나타나 정확한 원인을 파악하는 데 도움을 주기도 합니다.


주요 발생 원인

1. 변수 버퍼 크기 초과 (String Buffer Too Small)

가장 흔한 원인으로, VARCHAR2 또는 CHAR 타입 변수에 선언된 크기보다 더 긴 문자열을 할당하려 할 때 발생합니다. 예를 들어 VARCHAR2(10)으로 선언된 변수에 11자리 이상의 문자열을 넣으면 즉시 이 에러가 트리거됩니다. 실무에서는 외부 시스템에서 받아온 데이터가 예상보다 길 때 자주 발생하므로, 변수 선언 시 충분한 여유를 두는 것이 중요합니다.

2. 잘못된 타입 변환 (Invalid Type Conversion)

숫자형 변수(NUMBER, INTEGER 등)에 숫자로 변환할 수 없는 문자열을 할당하려 할 때 발생합니다. 예를 들어 'ABC'와 같은 문자열을 NUMBER 타입 변수에 대입하거나, TO_NUMBER('1,234') 형식으로 포맷이 맞지 않는 변환을 시도할 때 이 에러가 납니다. 특히 프런트엔드에서 입력받은 데이터를 검증 없이 PL/SQL로 넘길 경우 이 문제가 빈번히 발생합니다.

3. NUMBER 타입의 정밀도/스케일 초과 (Precision/Scale Overflow)

NUMBER(5,2)처럼 정밀도와 소수점 자릿수가 제한된 변수에 허용 범위를 초과하는 값을 대입할 때 발생합니다. 예를 들어 NUMBER(5,2) 변수에 1234.567을 넣으면, 정수부가 3자리(5-2=3)를 초과하거나 소수점 이하가 반올림 처리 과정에서 오류를 일으킬 수 있습니다. 금융, 회계 시스템에서 계산 결과를 저장할 때 특히 주의해야 합니다.


해결 방법

원인 1 해결: 변수 크기 조정 또는 %TYPE 사용

변수 선언 시 컬럼의 타입과 동일하게 %TYPE을 사용하면 데이터베이스 컬럼 크기 변경 시에도 자동으로 반영되어 유연성이 높아집니다.

-- 문제 발생 코드
DECLARE
  v_name VARCHAR2(10);
BEGIN
  -- 이름이 10자를 초과하면 ORA-06502 발생
  SELECT employee_name INTO v_name
  FROM employees
  WHERE employee_id = 101;
END;
/

-- 해결 방법 1: 충분한 크기로 변수 선언
DECLARE
  v_name VARCHAR2(200);
BEGIN
  SELECT employee_name INTO v_name
  FROM employees
  WHERE employee_id = 101;
  DBMS_OUTPUT.PUT_LINE('Name: ' || v_name);
END;
/

-- 해결 방법 2: %TYPE을 사용한 자동 타입 참조 (권장)
DECLARE
  v_name employees.employee_name%TYPE;
BEGIN
  SELECT employee_name INTO v_name
  FROM employees
  WHERE employee_id = 101;
  DBMS_OUTPUT.PUT_LINE('Name: ' || v_name);
END;
/

원인 2 해결: 타입 변환 전 유효성 검사

입력값이 숫자로 변환 가능한지 사전에 검사하거나, 예외 처리를 통해 안전하게 처리합니다.

-- 문제 발생 코드
DECLARE
  v_input VARCHAR2(50) := 'ABC123'; -- 숫자 변환 불가
  v_number NUMBER;
BEGIN
  v_number := TO_NUMBER(v_input); -- ORA-06502 발생
END;
/

-- 해결 방법 1: REGEXP를 이용한 사전 유효성 검사
DECLARE
  v_input  VARCHAR2(50) := 'ABC123';
  v_number NUMBER;
BEGIN
  IF REGEXP_LIKE(v_input, '^\d+(\.\d+)?$') THEN
    v_number := TO_NUMBER(v_input);
    DBMS_OUTPUT.PUT_LINE('변환 성공: ' || v_number);
  ELSE
    DBMS_OUTPUT.PUT_LINE('숫자 변환 불가: ' || v_input);
  END IF;
END;
/

-- 해결 방법 2: 예외 처리를 이용한 안전한 변환
DECLARE
  v_input  VARCHAR2(50) := 'ABC123';
  v_number NUMBER;
BEGIN
  BEGIN
    v_number := TO_NUMBER(v_input);
  EXCEPTION
    WHEN VALUE_ERROR THEN
      DBMS_OUTPUT.PUT_LINE('ORA-06502: 값 변환 오류 - 입력값: ' || v_input);
      v_number := 0; -- 기본값 설정
  END;
  DBMS_OUTPUT.PUT_LINE('결과: ' || v_number);
END;
/

-- 해결 방법 3: Oracle 12c 이상에서 VALIDATE_CONVERSION 함수 활용
DECLARE
  v_input  VARCHAR2(50) := '12345.67';
  v_number NUMBER;
BEGIN
  IF VALIDATE_CONVERSION(v_input AS NUMBER) = 1 THEN
    v_number := TO_NUMBER(v_input);
    DBMS_OUTPUT.PUT_LINE('변환 성공: ' || v_number);
  ELSE
    DBMS_OUTPUT.PUT_LINE('변환 불가한 값입니다.');
  END IF;
END;
/

원인 3 해결: NUMBER 정밀도 조정

-- 문제 발생 코드
DECLARE
  v_amount NUMBER(5, 2); -- 최대 999.99까지만 저장 가능
BEGIN
  v_amount := 12345.678; -- 정수부 5자리 초과 -> ORA-06502 발생
END;
/

-- 해결 방법 1: 정밀도 재설정
DECLARE
  v_amount NUMBER(12, 4); -- 충분한 정밀도 확보
BEGIN
  v_amount := 12345.6789;
  DBMS_OUTPUT.PUT_LINE('금액: ' || v_amount);
END;
/

-- 해결 방법 2: ROUND를 이용한 사전 처리
DECLARE
  v_amount NUMBER(8, 2);
  v_raw    NUMBER := 12345.6789;
BEGIN
  v_amount := ROUND(v_raw, 2); -- 소수점 2자리로 반올림 후 대입
  DBMS_OUTPUT.PUT_LINE('처리된 금액: ' || v_amount);
END;
/

-- 해결 방법 3: 범위 초과 여부 사전 체크
DECLARE
  v_amount NUMBER(5, 2);
  v_raw    NUMBER := 12345.67;
BEGIN
  IF v_raw BETWEEN -999.99 AND 999.99 THEN
    v_amount := ROUND(v_raw, 2);
  ELSE
    RAISE_APPLICATION_ERROR(-20001, '금액이 허용 범위를 초과했습니다: ' || v_raw);
  END IF;
END;
/

예방 방법

1. %TYPE 및 %ROWTYPE을 적극 활용하라

PL/SQL 변수를 선언할 때 리터럴 크기를 직접 지정하는 대신, %TYPE%ROWTYPE을 사용하면 테이블 컬럼 정의가 변경되더라도 코드 수정 없이 자동으로 적용됩니다. 이는 유지보수성을 크게 향상시키고, 버퍼 크기 불일치로 인한 ORA-06502 에러를 원천적으로 방지하는 가장 효과적인 방법입니다.

-- 권장 패턴
DECLARE
  v_emp_rec  employees%ROWTYPE;
  v_dept_name departments.department_name%TYPE;
BEGIN
  SELECT * INTO v_emp_rec FROM employees WHERE employee_id = 100;
  SELECT department_name INTO v_dept_name
  FROM departments WHERE department_id = v_emp_rec.department_id;
  DBMS_OUTPUT.PUT_LINE(v_emp_rec.first_name || ' - ' || v_dept_name);
END;
/

2. 입력 데이터 유효성 검사 레이어를 반드시 구현하라

외부 입력(사용자 입력, API 연동 데이터, 파일 업로드 등)을 PL/SQL 변수에 할당하기 전에 반드시 데이터 타입, 길이, 값의 범위를 검증하는 공통 유틸리티 패키지를 작성하여 사용하세요. 아래는 간단한 유효성 검사 패키지 예시입니다.

CREATE OR REPLACE PACKAGE pkg_validator AS
  FUNCTION is_valid_number(p_value IN VARCHAR2) RETURN BOOLEAN;
  FUNCTION safe_to_number(p_value IN VARCHAR2, p_default IN NUMBER DEFAULT 0) RETURN NUMBER;
  FUNCTION truncate_string(p_value IN VARCHAR2, p_max_len IN NUMBER) RETURN VARCHAR2;
END pkg_validator;
/

CREATE OR REPLACE PACKAGE BODY pkg_validator AS

  FUNCTION is_valid_number(p_value IN VARCHAR2) RETURN BOOLEAN IS
  BEGIN
    RETURN VALIDATE_CONVERSION(p_value AS NUMBER) = 1;
  END;

  FUNCTION safe_to_number(p_value IN VARCHAR2, p_default IN NUMBER DEFAULT 0) RETURN NUMBER IS
  BEGIN
    IF is_valid_number(p_value) THEN
      RETURN TO_NUMBER(p_value);
    ELSE
      RETURN p_default;
    END IF;
  END;

  FUNCTION truncate_string(p_value IN VARCHAR2, p_max_len IN NUMBER) RETURN VARCHAR2 IS
  BEGIN
    RETURN SUBSTR(p_value, 1, p_max_len);
  END;

END pkg_validator;
/

관련 에러

  • ORA-06500: PL/SQL: storage error — 메모리 관련 오류로, 매우 큰 컬렉션이나 대형 문자열 처리 시 발생합니다.
  • ORA-01722: invalid number — SQL 레이어에서 문자열을 숫자로 변환할 수 없을 때 발생하며, ORA-06502의 SQL 버전에 해당합니다.
  • ORA-01426: numeric overflow — NUMBER 타입의 최대 허용 범위(최대 38자리)를 초과할 때 발생합니다.
  • ORA-06511: PL/SQL: cursor already open — PL/SQL 런타임 에러 계열로, 커서 중복 오픈 시 발생하며 ORA-065xx 계열 에러 중 하나입니다.
  • ORA-04091: table is mutating — 트리거 내에서 자기 참조 테이블을 조회할 때 발생하며, 종종 잘못된 값 처리와 함께 ORA-06502와 같이 나타나기도 합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기