2026년 06월 08일 | DBMS Error 가이드
이 글에서 다루는 내용
22010 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
22010 invalid indicator parameter value 는?
PostgreSQL 에러 코드 22010은 “invalid indicator parameter value” 로, 호스트 변수(host variable)와 함께 사용되는 인디케이터(indicator) 파라미터에 유효하지 않은 값이 전달되었을 때 발생합니다. 이 에러는 주로 Embedded SQL(ECPG) 또는 ODBC, JDBC와 같은 외부 인터페이스를 통해 데이터베이스와 통신할 때, 인디케이터 변수에 허용 범위를 벗어난 값이 설정된 경우 트리거됩니다. SQL 표준에서 인디케이터 파라미터는 NULL 여부를 나타내거나 데이터 잘림(truncation) 상태를 표현하는 데 사용되며, 이 값이 규격을 벗어나면 PostgreSQL은 즉시 해당 에러를 반환합니다.
주요 발생 원인
1. Embedded SQL(ECPG)에서 잘못된 인디케이터 변수 값 사용
ECPG 프로그램에서 호스트 변수와 함께 인디케이터 변수를 선언하고 사용할 때, 인디케이터 변수에 음수 값이 아닌 임의의 값을 설정하는 경우 에러가 발생합니다. SQL 표준에 따르면 인디케이터 값은 -1(NULL을 나타냄), 0(정상값), 또는 양수(데이터 잘림 길이)만 허용됩니다. 예를 들어 인디케이터 변수에 -99나 999 같은 의미 없는 임의의 음수 또는 특정 양수를 넣는 경우 PostgreSQL은 이를 유효하지 않은 인디케이터 값으로 판단하고 22010 에러를 반환합니다.
2. ODBC/JDBC 드라이버의 잘못된 파라미터 바인딩
ODBC나 JDBC를 사용하여 PostgreSQL에 연결할 때, 파라미터 바인딩 과정에서 NULL 여부를 나타내는 인디케이터 버퍼에 잘못된 값이 설정되는 경우에도 이 에러가 발생할 수 있습니다. 특히 오래된 버전의 드라이버이거나, 커스텀 드라이버를 직접 구현한 경우 SQLBindParameter의 StrLen_or_IndPtr 인자에 표준에서 허용하지 않는 값을 전달하면 서버 측에서 22010을 반환하게 됩니다. 이 경우 드라이버의 버전 업그레이드나 파라미터 바인딩 코드를 재검토하는 것이 필요합니다.
3. 애플리케이션 레벨에서의 NULL 처리 로직 오류
애플리케이션 코드에서 SQL 쿼리에 파라미터를 전달할 때 NULL 처리 로직이 잘못 구현된 경우에도 22010 에러가 유발될 수 있습니다. 예를 들어, C 언어 기반의 ECPG 코드에서 인디케이터 변수를 초기화하지 않고 사용하거나, 다른 로직에서 이미 변경된 인디케이터 값을 재사용하는 경우, 예상치 못한 쓰레기 값(garbage value)이 인디케이터 파라미터로 전달될 수 있습니다. 이는 특히 멀티스레드 환경에서 인디케이터 변수가 공유될 때 더욱 빈번하게 나타나는 패턴입니다.
해결 방법
원인 1 해결: ECPG 인디케이터 변수 올바르게 설정하기
ECPG 코드에서 인디케이터 변수는 반드시 0, -1, 또는 양수(잘린 데이터의 원래 길이)로만 설정해야 합니다.
-- ECPG 예제: 올바른 인디케이터 변수 사용법
EXEC SQL BEGIN DECLARE SECTION;
char emp_name[50];
short emp_name_ind; /* 인디케이터 변수 */
int emp_id;
short emp_id_ind;
EXEC SQL END DECLARE SECTION;
-- NULL이 아닌 정상값을 삽입할 때: 인디케이터를 0으로 설정
emp_name_ind = 0; /* 정상 값 */
strcpy(emp_name, "홍길동");
emp_id_ind = 0;
emp_id = 1001;
EXEC SQL INSERT INTO employees (id, name)
VALUES (:emp_id :emp_id_ind, :emp_name :emp_name_ind);
-- NULL 값을 삽입할 때: 인디케이터를 -1로 설정
emp_name_ind = -1; /* NULL을 나타냄 */
EXEC SQL INSERT INTO employees (id, name)
VALUES (:emp_id :emp_id_ind, :emp_name :emp_name_ind);
잘못된 방식과 올바른 방식을 비교한 예:
-- ❌ 잘못된 방법: 임의의 값으로 인디케이터 설정 -> 22010 에러 유발
emp_name_ind = -99; /* 유효하지 않은 인디케이터 값 */
-- ✅ 올바른 방법: NULL을 표현할 때는 반드시 -1 사용
emp_name_ind = -1; /* SQL 표준에 따른 NULL 인디케이터 */
원인 2 해결: ODBC 파라미터 바인딩 수정
ODBC 기반 애플리케이션에서는 SQLBindParameter 함수 호출 시 StrLen_or_IndPtr 인자를 올바르게 설정해야 합니다.
-- PostgreSQL 테이블 예시
CREATE TABLE product_inventory (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
description TEXT, -- NULL 허용
quantity INTEGER DEFAULT 0
);
-- ODBC C 코드에서의 올바른 파라미터 바인딩 (의사코드)
-- SQLLEN desc_ind = SQL_NULL_DATA; // NULL 전달 시
-- SQLLEN desc_ind = SQL_NTS; // 문자열 전달 시 (Null-Terminated String)
-- SQLLEN qty_ind = 0; // 정수형 정상값 전달 시
-- 검증 쿼리: 실제 데이터가 올바르게 들어갔는지 확인
SELECT
product_id,
product_name,
CASE WHEN description IS NULL THEN 'NULL(인디케이터 -1 사용됨)'
ELSE description
END AS description_status,
quantity
FROM product_inventory
ORDER BY product_id DESC
LIMIT 10;
원인 3 해결: 인디케이터 변수 초기화 및 재사용 방지
-- ECPG에서 인디케이터 변수를 루프 내에서 사용할 때 반드시 재초기화
EXEC SQL BEGIN DECLARE SECTION;
int emp_id;
short emp_id_ind;
char emp_name[100];
short emp_name_ind;
double salary;
short salary_ind;
EXEC SQL END DECLARE SECTION;
-- 루프 내에서 매번 인디케이터를 명시적으로 초기화
for (int i = 0; i < record_count; i++) {
/* 매 반복마다 인디케이터 초기화 */
emp_id_ind = 0;
emp_name_ind = 0;
salary_ind = (data[i].salary == UNDEFINED) ? -1 : 0;
emp_id = data[i].id;
strcpy(emp_name, data[i].name);
salary = data[i].salary;
EXEC SQL INSERT INTO employees (id, name, salary)
VALUES (:emp_id :emp_id_ind,
:emp_name :emp_name_ind,
:salary :salary_ind);
}
-- 삽입 후 NULL 처리가 올바르게 되었는지 검증
SELECT
id,
name,
salary,
(salary IS NULL) AS is_salary_null
FROM employees
WHERE id IN (SELECT id FROM employees ORDER BY id DESC LIMIT 5);
예방 방법
1. 인디케이터 변수에 대한 래퍼 함수/매크로 도입
인디케이터 변수를 직접 다루는 코드 전반에 걸쳐 허용된 값(-1, 0, 양수)만 설정할 수 있도록 래퍼 매크로나 인라인 함수를 도입하는 것이 좋습니다. 이를 통해 개발자가 임의의 값을 실수로 설정하는 것을 원천 차단할 수 있으며, 코드 리뷰 시에도 인디케이터 설정이 명확히 드러나 유지보수성이 향상됩니다. 아래와 같이 공통 유틸리티 함수를 만들어 팀 전체가 공유하는 것을 권장합니다.
-- PostgreSQL 함수로 인디케이터 유효성 검사를 시뮬레이션하는 예
-- (실제 인디케이터 검증은 클라이언트 레이어에서 수행되어야 함)
CREATE OR REPLACE FUNCTION validate_indicator_value(p_indicator INTEGER)
RETURNS BOOLEAN
LANGUAGE plpgsql
AS $$
BEGIN
-- 인디케이터 값은 -1(NULL), 0(정상), 양수(잘린 길이)만 허용
IF p_indicator < -1 THEN
RAISE EXCEPTION 'Invalid indicator value: %. Must be -1 (NULL), 0 (normal), or positive (truncation length).', p_indicator
USING ERRCODE = '22010';
END IF;
RETURN TRUE;
END;
$$;
-- 사용 예시
SELECT validate_indicator_value(0); -- TRUE (정상)
SELECT validate_indicator_value(-1); -- TRUE (NULL 표현)
SELECT validate_indicator_value(10); -- TRUE (잘린 길이)
SELECT validate_indicator_value(-99); -- ERROR: 22010
2. 연결 풀링과 드라이버 버전 관리 정책 수립
PgBouncer나 pgpool-II 같은 연결 풀러를 사용하는 환경에서는 드라이버 버전과 미들웨어 버전 간의 호환성을 정기적으로 검증해야 합니다. 특히 PostgreSQL 메이저 버전 업그레이드 이후에는 ODBC/JDBC 드라이버를 함께 업그레이드하고, 파라미터 바인딩 동작이 달라졌는지 통합 테스트를 반드시 수행하는 것이 좋습니다. 이와 함께 CI/CD 파이프라인에 인디케이터 파라미터를 포함한 NULL 처리 시나리오에 대한 자동화 테스트를 추가하면 배포 전에 22010 에러를 조기에 발견할 수 있습니다.
관련 에러
22000– data exception: 22010은 22000 카테고리(데이터 예외, Data Exception)의 하위 에러입니다. 데이터 값 자체의 형식이나 범위 문제로 발생하는 상위 범주에 해당합니다.22002– null value, no indicator parameter: NULL 값이 반환되었는데 인디케이터 변수가 제공되지 않은 경우 발생합니다. 22010과 반대 방향의 인디케이터 관련 에러로 함께 이해해두면 좋습니다.22001– string data right truncation: 문자열 데이터가 대상 컬럼 크기를 초과하여 잘릴 때 발생하며, 인디케이터 값에 잘림 길이를 포함해야 하는 경우와 연관됩니다.22003– numeric value out of range: 숫자형 파라미터 값이 허용 범위를 벗어났을 때 발생하며, 인디케이터 파라미터 처리와 유사한 맥락에서 파라미터 바인딩 오류로 함께 나타나는 경우가 많습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.