PostgreSQL 2201E 오류: 원인과 해결책 완전 가이드

발행: (2026년 6월 6일 AM 09:03 GMT+9)
5 분 소요
원문: Dev.to

PostgreSQL 오류 2201E: 로그 함수의 잘못된 인수

PostgreSQL 오류 2201E (invalid_argument_for_logarithm)는 로그 함수(LN(), LOG(), LOG10())에 인수로 0 또는 음수가 전달될 때 발생합니다. 수학적으로 로그는 양의 실수에 대해서만 정의되므로, PostgreSQL은 실행 시점에 이 도메인 규칙을 강제합니다. 이 오류는 금융 데이터, 과학 계산, 혹은 입력값 검증이 충분히 이루어지지 않은 숫자 파이프라인 등에서 흔히 나타납니다.

가장 단순한 원인: 리터럴 0이나 음수를 직접 로그 함수에 넘기거나, 해당 값을 포함하고 있는 컬럼을 사용하는 경우입니다.

-- 모두 ERROR 2201E를 발생시킵니다
SELECT LN(0);
SELECT LOG(10, -5);
SELECT LN(price) FROM products;  -- price가 0이거나 0 이하인 행이 있으면 실패

안전하게 고치는 방법 – CASE 사용

SELECT
    product_id,
    CASE WHEN price > 0 THEN LN(price) ELSE NULL END AS ln_price
FROM products;

원시 컬럼은 안전해 보여도 SUM(), 뺄셈 등 연산 결과가 특정 데이터 조합에 따라 0 또는 음수가 될 수 있습니다.

-- 위험: profit이 0이거나 음수가 될 수 있음
SELECT
    department,
    LN(SUM(revenue) - SUM(expenses)) AS log_profit
FROM financials
GROUP BY department;

안전한 해결책 – HAVING 절로 필터링

SELECT
    department,
    LN(SUM(revenue) - SUM(expenses)) AS log_profit
FROM financials
GROUP BY department
HAVING (SUM(revenue) - SUM(expenses)) > 0;

안전한 해결책 – NULL 반환을 위한 CASE

SELECT
    department,
    CASE
        WHEN (SUM(revenue) - SUM(expenses)) > 0
        THEN LN(SUM(revenue) - SUM(expenses))
        ELSE NULL
    END AS log_profit
FROM financials
GROUP BY department;

사용자 입력, CSV 임포트, API 피드 등에서 데이터가 예기치 않게 0 또는 음수가 될 수 있음

-- 로그 함수를 적용하기 전에 데이터를 감사하세요
SELECT id, metric_value,
    CASE
        WHEN metric_value IS NULL THEN 'NULL'
        WHEN metric_value > 0 THEN LN(metric_value) ELSE NULL END
FROM some_table;

집계 결과에 HAVING 절 추가

SELECT ...
FROM ...
GROUP BY ...
HAVING sum_col > 0;

반복 사용을 위한 안전한 래퍼 함수 만들기

-- 예시: safe_ln() 함수 정의 후 사용

1️⃣ 양수 값 강제 – CHECK 제약조건

테이블 수준에서 CHECK 제약조건을 추가하면 잘못된 값이 처음부터 데이터베이스에 들어오는 것을 차단할 수 있습니다.

CREATE TABLE metrics (
    id      SERIAL PRIMARY KEY,
    value   NUMERIC CHECK (value > 0)
);

기존 테이블에 추가하려면:

ALTER TABLE metrics
    ADD CONSTRAINT chk_value_positive CHECK (value > 0);

2️⃣ 로그 로직을 안전한 뷰 또는 함수에 캡슐화

모든 로그 계산을 뷰나 저장 함수로 추상화하고, 내부에 방어 로직을 포함시킵니다. 이렇게 하면 로직을 사용하는 모든 쿼리가 자동으로 보호받으며, 매번 방어 조건을 다시 작성할 필요가 없습니다.

CREATE OR REPLACE VIEW safe_metric_logs AS
SELECT
    id,
    value,
    CASE WHEN value > 0 THEN LN(value)      ELSE NULL END AS ln_value,
    CASE WHEN value > 0 THEN LOG(10, value) ELSE NULL END AS log10_value
FROM metrics;

관련 오류 코드

  • 22012 division_by_zero — 0으로 나누는 경우 발생하는 유사 도메인 위반 오류.
  • 2201F invalid_argument_for_power_function — 거듭제곱/지수 함수에 잘못된 인수가 들어갔을 때 발생.
  • 2201G invalid_argument_for_width_bucket_functionWIDTH_BUCKET()에 부적절한 인수가 전달된 경우.

📖 더 자세한 가이드를 원하시나요?
oraerror.com — 상세 분석, 추가 SQL 예제, 예방 팁 등을 제공합니다.

0 조회
Back to Blog

관련 글

더 보기 »

모바일 한여름 열풍

!Cover image for Mobile Midsommer Madnesshttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploa...