PostgreSQL 22036 오류: 원인과 해결책 완전 가이드
출처: Dev.to
PostgreSQL 오류 22036: 비숫자 SQL JSON 항목
PostgreSQL 오류 코드 22036 (non numeric sql json item) 은 SQL/JSON 경로 표현식이 숫자가 아닌 JSON 항목(문자열, 불리언, 배열, 객체 등)에 대한 연산을 시도할 때 발생합니다. 이 오류는 PostgreSQL 12에서 SQL/JSON Path 기능이 도입될 때 함께 등장했으며, jsonb_path_query, jsonb_path_exists 또는 @@와 @? 연산자를 사용하는 쿼리에서 주로 나타납니다.
가장 흔한 원인은 숫자가 따옴표로 감싸여 있는 JSON 데이터입니다(예: "price": "100" 대신 "price": 100). 외부 API나 타입 일관성을 강제하지 않는 레거시 시스템에서 자주 발생합니다.
— 22036 오류 발생: "price"는 문자열이며, 숫자가 아닙니다
SELECT jsonb_path_query(’{“price”: “100”}’, ‘$.price + 50’);
— ERROR: non numeric SQL/JSON item
— 수정: JSON 경로 내에서 .double() 메서드 사용
SELECT jsonb_path_query(’{“price”: “100”}’, ‘$.price.double() + 50’);
— 결과: 150
— 대체 수정: SQL 수준에서 캐스팅
SELECT (data->>‘price’)::numeric + 50
FROM (SELECT ’{“price”: “100”}‘::jsonb AS data) t;
— 결과: 150
개발자는 JSON Path 표현식이 전체 배열이나 객체를 대상으로 하고 개별 요소를 다루지 않은 채 arithmetic 연산을 시도하는 경우가 있습니다.
— 22036 오류 발생: $.scores는 배열을 반환하고, 숫자가 아님
SELECT jsonb_path_query(’{“scores”: [80, 90, 70]}’, ‘$.scores + 10’);
— ERROR: non numeric SQL/JSON item
— 수정: 특정 배열 인덱스 지정
SELECT jsonb_path_query(’{“scores”: [80, 90, 70]}’, ‘$.scores[0] + 10’);
— 결과: 90
— 수정: 와일드카드를 사용해 각 요소를 적용
SELECT jsonb_path_query(’{“scores”: [80, 90, 70]}’, ‘$.scores[* ] + 10’);
— 결과: 90, 100, 80
— 수정: 배열 요소 순회를 위해 unnest 사용
SELECT elem::numeric + 10
FROM jsonb_array_elements(
’{“scores”: [80, 90, 70]}‘::jsonb -> ‘scores’
) AS elem;
JSON 필드에 null, true, false가 포함되고 numeric JSON Path 연산을 적용할 때 PostgreSQL이 22036 오류를 발생시킵니다. 이는 누락된 값이 기본값으로 null이 되거나, 상태 플래그가 불리언으로 저장되는 데이터셋에서 흔합니다.
— 22036 오류 발생: null은 숫자가 아님
SELECT jsonb_path_query(’{“value”: null}’, ‘$.value + 10’);
— ERROR: non numeric SQL/JSON item
— 수정: JSON Path 내에서 타입 필터링
SELECT jsonb_path_query(
’{“items”: [10, null, 30]}’,
‘$.items[*] ? (@ != null)’
);
— 결과: 10, 30
— 수정: SQL 수준에서 jsonb_typeof로 보호
SELECT
CASE
WHEN jsonb_typeof(data -> ‘value’) = ‘number’
THEN (data ->> ‘value’)::numeric + 10
ELSE NULL
END AS result
FROM (SELECT ’{“value”: null}‘::jsonb AS data) t;
— 결과: NULL (오류 없음)
이 재사용 가능한 헬퍼 함수를 사용하면Production 환경에서 22036 오류를 일으키지 않고任何 JSON 문서에서 안전하게 숫자 값을 추출할 수 있습니다:
CREATE OR REPLACE FUNCTION safe_json_numeric(
p_data jsonb,
p_path text,
p_default numeric DEFAULT 0
) RETURNS numeric LANGUAGE plpgsql AS $$
DECLARE
v_raw text;
BEGIN
v_raw := jsonb_path_query_first(p_data, p_path::jsonpath)::text;
IF v_raw IS NULL OR v_raw = 'null' THEN
RETURN p_default;
END IF;
RETURN v_raw::numeric;
EXCEPTION
WHEN SQLSTATE '22036' THEN RETURN p_default;
WHEN others THEN RETURN p_default;
END;
$$;
— 사용 예시
SELECT safe_json_numeric(’{“price”: “99.9”}‘::jsonb, ‘$.price’, 0);
— 결과: 99.9
SELECT safe_json_numeric(’{“price”: null}‘::jsonb, ‘$.price’, -1);
— 결과: -1
INSERT 시 CHECK 제약을 통해 타입을 강제할 수 있습니다:
CREATE TABLE orders (
id serial PRIMARY KEY,
data jsonb NOT NULL,
CONSTRAINT chk_amount_is_number
CHECK (jsonb_typeof(data -> 'amount') = 'number')
);
JSON Path arithmetic 쿼리 실행 전 타입 검증을 반드시 수행하십시오:
항상 numeric JSON Path 연산과 jsonb_typeof() guardia 혹은 ? (@ != null) 필터를 함께 사용하십시오. 외부 소스 JSON은 신뢰하지 않고 명시적으로 타입을 검증한 뒤 처리하십시오. 이 간단한 습관이 프로덕션 시스템에서 22036 오류의 대부분을 제거합니다.
Code Name Notes
22032
invalid input syntax for type json
Malformed JSON at parse time
22033
invalid SQL JSON subscript
Bad array index in JSON Path
22034
more than one SQL JSON item
Multiple items where one expected
22035
no SQL JSON item
Empty result where one required
📖 더 자세한 가이드가 필요하신가요? oraerror.com — 상세 분석, 추가 SQL 예시, 그리고 예방 팁을 포함합니다.