2026년 10월 05일 | DBMS Error 가이드
이 글에서 다루는 내용
01003 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
01003 null value eliminated in set function 는?
PostgreSQL 에러 코드 01003은 엄밀히 말하면 에러(ERROR)가 아니라 경고(WARNING) 수준의 메시지입니다. 이 경고는 SUM(), AVG(), COUNT(), MAX(), MIN() 등의 집계 함수(Set Function)를 사용할 때, 대상 컬럼에 NULL 값이 포함되어 있어 해당 NULL 값이 자동으로 제외된 채 연산이 수행될 때 발생합니다. 대부분의 경우 쿼리는 정상적으로 실행되지만, NULL이 제거됨으로써 비즈니스 로직상 의도하지 않은 결과가 도출될 수 있기 때문에 반드시 주의 깊게 살펴봐야 합니다.
주요 발생 원인
1. NULL 값이 포함된 컬럼에 집계 함수 직접 적용
가장 빈번하게 발생하는 원인입니다. 테이블 설계 단계에서 특정 컬럼에 NOT NULL 제약 조건을 걸지 않은 경우, 데이터 입력 과정에서 NULL 값이 자연스럽게 쌓이게 됩니다. 이후 해당 컬럼에 SUM() 이나 AVG() 같은 집계 함수를 적용하면, PostgreSQL은 NULL 값을 무시하고 계산을 진행하면서 01003 경고를 발생시킵니다.
-- 예시: 급여 컬럼에 NULL이 존재하는 경우
SELECT AVG(salary)
FROM employees;
-- salary 컬럼에 NULL이 있으면 01003 경고 발생
2. JOIN 결과로 인해 생성된 NULL 값에 집계 함수 적용
LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN 등을 사용하면 매칭되지 않는 행의 컬럼 값이 NULL로 채워집니다. 이 JOIN 결과셋에 바로 집계 함수를 적용하면 의도치 않게 다수의 NULL이 포함될 수 있습니다. 특히 복잡한 다중 JOIN 쿼리에서는 어느 조인 단계에서 NULL이 발생했는지 추적하기 어려워 디버깅이 까다롭습니다.
-- 예시: LEFT JOIN 후 집계 시 NULL 발생
SELECT d.department_name, SUM(e.salary) AS total_salary
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
GROUP BY d.department_name;
-- 직원이 없는 부서의 e.salary는 NULL → 01003 경고
3. 데이터 이관 또는 ETL 과정에서의 NULL 유입
외부 시스템에서 데이터를 이관하거나 ETL(Extract, Transform, Load) 파이프라인을 통해 데이터를 적재할 때, 소스 시스템의 빈 값이나 미입력 값이 NULL로 변환되어 PostgreSQL 테이블에 삽입되는 경우가 많습니다. 이러한 데이터 품질 문제를 사전에 검증하지 않고 집계 쿼리를 수행하면, 집계 결과가 실제 비즈니스 현황과 다르게 산출되어 의사결정 오류로 이어질 수 있습니다.
-- 예시: 외부 CSV 임포트 후 집계
COPY sales_data(product_id, revenue, quantity)
FROM '/tmp/sales.csv' DELIMITER ',' CSV HEADER;
-- 이후 revenue에 NULL이 존재할 경우
SELECT product_id, SUM(revenue) AS total_revenue
FROM sales_data
GROUP BY product_id;
-- 01003 경고 발생 가능
해결 방법
원인 1 해결: COALESCE 또는 NULLIF 활용
집계 함수 내부에서 COALESCE()를 사용하면 NULL 값을 지정한 기본값으로 대체하여 경고를 방지하고 정확한 결과를 얻을 수 있습니다.
-- COALESCE로 NULL을 0으로 대체
SELECT AVG(COALESCE(salary, 0)) AS avg_salary
FROM employees;
-- SUM에서도 동일하게 적용
SELECT SUM(COALESCE(salary, 0)) AS total_salary
FROM employees;
-- NULL 행 자체를 제외하고 싶다면 WHERE 절 활용
SELECT AVG(salary) AS avg_salary
FROM employees
WHERE salary IS NOT NULL;
원인 2 해결: JOIN 후 NULL 처리 명시화
-- COALESCE로 JOIN 결과의 NULL 처리
SELECT
d.department_name,
SUM(COALESCE(e.salary, 0)) AS total_salary,
COUNT(e.emp_id) AS employee_count -- NULL은 COUNT에서 자동 제외됨
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
GROUP BY d.department_name;
-- 또는 FILTER 절을 활용한 조건부 집계
SELECT
d.department_name,
SUM(e.salary) FILTER (WHERE e.salary IS NOT NULL) AS total_salary
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
GROUP BY d.department_name;
원인 3 해결: ETL 이전 데이터 품질 검증
-- 이관 전 NULL 현황 파악
SELECT
COUNT(*) AS total_rows,
COUNT(revenue) AS non_null_revenue,
COUNT(*) - COUNT(revenue) AS null_revenue_count,
ROUND(
(COUNT(*) - COUNT(revenue))::NUMERIC / COUNT(*) * 100, 2
) AS null_percentage
FROM sales_data;
-- NULL이 허용되지 않아야 하는 컬럼에 DEFAULT 값 설정 후 이관
ALTER TABLE sales_data ALTER COLUMN revenue SET DEFAULT 0;
-- 이관 후 NULL 일괄 업데이트
UPDATE sales_data
SET revenue = 0
WHERE revenue IS NULL;
예방 방법
1. 테이블 설계 단계에서 NOT NULL 제약 조건 및 DEFAULT 값 명시
테이블을 처음 설계할 때부터 비즈니스 규칙상 반드시 값이 존재해야 하는 컬럼에는 NOT NULL 제약 조건과 함께 적절한 DEFAULT 값을 정의하는 것이 가장 근본적인 예방책입니다. 이렇게 하면 데이터 삽입 단계에서 NULL 유입 자체를 차단할 수 있습니다.
-- 테이블 생성 시 NOT NULL과 DEFAULT 함께 정의
CREATE TABLE employees (
emp_id SERIAL PRIMARY KEY,
emp_name VARCHAR(100) NOT NULL,
salary NUMERIC(12, 2) NOT NULL DEFAULT 0,
bonus NUMERIC(12, 2) NOT NULL DEFAULT 0,
dept_id INTEGER NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
2. 집계 쿼리에서는 항상 COALESCE와 IS NOT NULL 검증 루틴 표준화
팀 내 SQL 코딩 컨벤션을 수립하여, 집계 함수를 사용하는 모든 쿼리에서는 반드시 COALESCE()를 적용하거나 NULL 여부를 명시적으로 확인하는 것을 표준 관행으로 삼아야 합니다. 또한 pg_stat_user_tables 등의 시스템 뷰와 정기적인 데이터 품질 점검 쿼리를 스케줄링하여 NULL 비율이 급증하는 컬럼을 조기에 탐지하는 모니터링 체계를 구축하는 것이 중요합니다.
-- 정기 데이터 품질 점검 예시 (cron job 또는 pg_cron으로 스케줄링)
SELECT
table_name,
column_name,
null_frac,
n_distinct
FROM pg_stats
WHERE schemaname = 'public'
AND null_frac > 0.1 -- NULL 비율이 10% 초과인 컬럼 모니터링
ORDER BY null_frac DESC;
관련 에러
22004(null_value_not_allowed): NULL 값이 허용되지 않는 컨텍스트에서 NULL을 반환하려 할 때 발생하는 에러로,01003과 반대 성격의 상황입니다.22003(numeric_value_out_of_range): 집계 결과가 해당 데이터 타입의 범위를 초과할 때 발생하며, NULL 처리 후 집계 로직 변경 시 함께 확인해야 합니다.42803(grouping_error):GROUP BY절과SELECT절의 컬럼 불일치로 발생하는 에러로, 집계 쿼리 작성 시01003과 함께 자주 마주치게 됩니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.