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

ORA-01406
2026년 07월 11일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-01406 fetched column value was truncated 는?

ORA-01406 에러는 Oracle 데이터베이스에서 데이터를 페치(fetch)할 때, 가져온 컬럼의 값이 바인드 변수 또는 호스트 변수에 할당된 버퍼 크기보다 커서 값이 잘리는(truncated) 상황에서 발생합니다. 주로 Pro*C, OCI(Oracle Call Interface), JDBC, ODBC 등의 외부 프로그램에서 SQL 쿼리 결과를 변수에 담을 때 버퍼 크기를 충분히 설정하지 않았을 경우 나타납니다. 이 에러는 데이터 무결성과 직결되므로, 반드시 원인을 파악하고 적절히 처리해야 합니다.


주요 발생 원인

1. 호스트 변수(Host Variable) 또는 바인드 변수 버퍼 크기 부족

가장 빈번하게 발생하는 원인으로, Pro*C나 OCI 프로그램에서 선언한 변수의 크기가 실제 데이터베이스 컬럼에 저장된 데이터의 길이보다 작을 때 발생합니다. 예를 들어, 데이터베이스의 컬럼이 VARCHAR2(200)으로 정의되어 있는데, C 프로그램에서 char 배열을 50바이트로만 선언했다면 해당 컬럼에 100자짜리 데이터가 저장된 경우 반드시 이 에러가 발생하게 됩니다.

2. JDBC 또는 ODBC 드라이버에서 컬럼 매핑 타입 불일치

Java 애플리케이션에서 JDBC를 사용할 때, ResultSet에서 데이터를 읽어오는 과정에서 컬럼의 실제 데이터 타입과 Java 변수의 타입이 맞지 않거나, String 변수에 할당 가능한 크기를 초과한 경우에도 발생할 수 있습니다. 특히 CLOB, LONG, VARCHAR2와 같이 대용량 텍스트 데이터를 처리할 때 고정 길이 버퍼를 사용하면 문제가 심화됩니다.

3. PL/SQL 내 VARCHAR2 변수 선언 크기 부족

PL/SQL 블록 또는 저장 프로시저에서 변수를 선언할 때, 컬럼의 최대 길이를 고려하지 않고 임의의 크기로 선언한 경우에도 ORA-01406이 발생할 수 있습니다. 특히 데이터가 시간이 지남에 따라 점점 길어지는 경우(예: 비고 필드, 주소 필드 등), 처음에는 문제없이 동작하다가 특정 시점 이후부터 갑자기 에러가 발생하는 패턴을 보이기도 합니다.


해결 방법

원인 1 해결: 호스트 변수 버퍼 크기 확장

실제 컬럼의 최대 크기를 먼저 확인한 뒤, 그에 맞게 버퍼를 충분히 크게 선언합니다.

먼저 컬럼의 실제 정의를 확인합니다:

-- 컬럼 정의 및 실제 데이터 최대 길이 확인
SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, CHAR_LENGTH
FROM   USER_TAB_COLUMNS
WHERE  TABLE_NAME = 'YOUR_TABLE_NAME'
AND    COLUMN_NAME = 'YOUR_COLUMN_NAME';

-- 실제 저장된 데이터의 최대 길이 확인
SELECT MAX(LENGTH(your_column)) AS MAX_LEN
FROM   your_table;

Pro*C 코드에서의 수정 예시 (개념적):

-- PL/SQL에서 올바른 변수 선언 방법 (컬럼 타입 참조 방식 권장)
DECLARE
    -- 잘못된 방법: 고정 크기 선언
    -- v_description VARCHAR2(50);

    -- 올바른 방법 1: 컬럼의 %TYPE 사용 (컬럼 타입 자동 참조)
    v_description your_table.description%TYPE;

    -- 올바른 방법 2: 충분히 큰 크기로 선언
    v_description2 VARCHAR2(4000);
BEGIN
    SELECT description
    INTO   v_description
    FROM   your_table
    WHERE  id = 1;

    DBMS_OUTPUT.PUT_LINE('값: ' || v_description);
END;
/

원인 2 해결: LONG 또는 대용량 컬럼 처리

LONG 타입 컬럼이나 대용량 데이터가 포함된 경우, CLOB으로 변환하거나 적절한 처리를 추가합니다:

-- LONG 타입을 CLOB으로 변환하여 처리하는 방법
-- (LONG 컬럼을 직접 사용 시 ORA-01406 위험 존재)
CREATE TABLE new_table AS
SELECT id,
       TO_LOB(long_column) AS clob_column
FROM   old_table_with_long;

-- 또는 SUBSTR을 활용하여 필요한 길이만 잘라서 사용
SELECT id,
       SUBSTR(long_column, 1, 4000) AS trimmed_value
FROM   your_table;

원인 3 해결: PL/SQL 변수 선언 개선

-- 문제가 발생하는 코드 예시
DECLARE
    v_address VARCHAR2(100); -- 컬럼이 VARCHAR2(500)인데 100으로 선언
BEGIN
    SELECT address
    INTO   v_address
    FROM   customers
    WHERE  customer_id = 101; -- address가 100자 초과 시 에러 발생
END;
/

-- 해결된 코드 예시 (%TYPE 활용)
DECLARE
    v_address customers.address%TYPE; -- 컬럼 타입을 자동으로 참조
BEGIN
    SELECT address
    INTO   v_address
    FROM   customers
    WHERE  customer_id = 101;

    DBMS_OUTPUT.PUT_LINE('주소: ' || v_address);
EXCEPTION
    WHEN VALUE_ERROR THEN
        DBMS_OUTPUT.PUT_LINE('값이 너무 큽니다. 버퍼 크기를 확인하세요.');
END;
/

JDBC에서의 처리 방법 (SQL 관점)

-- JDBC에서 대용량 컬럼 조회 시 명시적 캐스팅 활용
SELECT id,
       CAST(description AS VARCHAR2(4000)) AS description,
       DBMS_LOB.SUBSTR(clob_column, 4000, 1) AS clob_preview
FROM   your_table
WHERE  id = 1;

-- 데이터 길이 사전 검증 쿼리 (애플리케이션 배포 전 점검용)
SELECT column_name,
       MAX(LENGTH(column_name)) AS max_actual_length,
       data_length AS defined_length
FROM   user_tab_columns utc
JOIN   your_table yt ON 1=1
WHERE  utc.table_name = 'YOUR_TABLE'
GROUP BY column_name, data_length
HAVING MAX(LENGTH(column_name)) > data_length;

예방 방법

1. PL/SQL 변수 선언 시 %TYPE 또는 %ROWTYPE 속성 항상 사용

변수를 선언할 때 반드시 컬럼의 %TYPE 또는 로우의 %ROWTYPE을 사용하는 코딩 표준을 수립하고 팀 전체에 적용해야 합니다. 이 방법을 사용하면 DBA가 컬럼의 데이터 타입이나 크기를 변경하더라도 PL/SQL 코드가 자동으로 새로운 타입을 반영하므로, ORA-01406을 포함한 다양한 타입 관련 에러를 사전에 방지할 수 있습니다.

-- Best Practice: %TYPE과 %ROWTYPE 활용 예시
DECLARE
    -- 단일 컬럼 참조
    v_emp_name  employees.last_name%TYPE;
    v_salary    employees.salary%TYPE;

    -- 전체 로우 참조
    r_emp       employees%ROWTYPE;
BEGIN
    SELECT last_name, salary
    INTO   v_emp_name, v_salary
    FROM   employees
    WHERE  employee_id = 100;

    SELECT *
    INTO   r_emp
    FROM   employees
    WHERE  employee_id = 100;

    DBMS_OUTPUT.PUT_LINE('이름: ' || r_emp.last_name);
    DBMS_OUTPUT.PUT_LINE('급여: ' || r_emp.salary);
END;
/

2. 배포 전 데이터 길이 사전 검증 쿼리 실행

신규 기능 배포 또는 데이터 마이그레이션 전에 반드시 실제 데이터의 최대 길이와 변수/버퍼 크기를 비교하는 검증 쿼리를 실행하는 프로세스를 수립합니다. 이를 자동화된 배포 파이프라인(CI/CD)에 포함시키면 운영 환경에서의 예상치 못한 에러를 사전에 차단할 수 있습니다.

-- 배포 전 데이터 검증 스크립트 예시
SELECT t.table_name,
       c.column_name,
       c.data_type,
       c.data_length                          AS defined_max_length,
       MAX(LENGTH(CAST(col_value AS VARCHAR2(32767)))) AS actual_max_length,
       CASE
           WHEN MAX(LENGTH(CAST(col_value AS VARCHAR2(32767)))) > c.data_length
           THEN '⚠️ 주의: 실제 데이터가 정의 길이 초과'
           ELSE '✅ 정상'
       END AS status
FROM   user_tab_columns c
-- 실제 운영 시에는 동적 SQL로 각 컬럼을 순회하는 프로시저 작성 권장
;

관련 에러

  • ORA-01401: inserted value too large for column — 삽입 시 컬럼 크기 초과. ORA-01406이 읽기(fetch) 단계의 문제라면, ORA-01401은 쓰기(insert) 단계의 유사한 문제입니다.
  • ORA-06502: PL/SQL: numeric or value error: character string buffer too small — PL/SQL 내에서 변수에 값을 할당할 때 버퍼가 작을 경우 발생하며, ORA-01406과 함께 나타나는 경우가 많습니다.
  • ORA-01403: no data found — SELECT INTO 구문에서 데이터가 없을 때 발생하며, ORA-01406과 함께 FETCH 관련 에러로 묶어서 예외 처리하는 것이 좋습니다.
  • ORA-22813: operand value exceeds system limits — LOB 또는 오브젝트 타입 처리 시 크기 제한을 초과할 때 발생하는 에러로, 대용량 데이터 처리 시 함께 고려해야 합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기