PostgreSQL 22030 오류: 원인과 해결책 완전 가이드
출처: Dev.to
PostgreSQL 오류 22030: 중복 JSON 객체 키 값
PostgreSQL 오류 코드 22030은 JSON 객체에 중복 키가 포함되어 JSON 사양(RFC 7159)을 위반할 때 발생합니다. 이 오류는 주로 jsonb_build_object(), json_object_agg()을 사용할 때 혹은 외부에서 생성된 중복 키를 포함하는 JSON 문자열을 jsonb 컬럼에 삽입할 때 가장 흔히 나타납니다.
jsonb_ build_object()
이것이 가장 일반적인 원인입니다. 개발자는 동적으로 JSON 객체를 구성할 때 같은 키를 두 번 전달하는 실수를 합니다.
— 이 코드는 ERROR 22030을 발생시킵니다
SELECT jsonb_build_object(‘user’, ‘Alice’, ‘score’, 100, ‘user’, ‘Bob’);
— 수정: 중복 키 제거
SELECT jsonb_ build_object(‘user’, ‘Alice’, ‘score’, 100);
— 또는 distint 키 이름 사용
SELECT jsonb_build_object(‘first_user’, ‘Alice’, ‘second_user’, ‘Bob’, ‘score’, 100);
jsonb 컬럼
외부 API나 레거시 시스템은 중복 키가 포함된 JSON을 가끔 생성합니다. json 타입은 이를 허용하지만 jsonb는 허용하지 않습니다.
— json 타입은 중복 키 허용 (오류 없음)
SELECT ’{“name”: “Alice”, “name”: “Bob”}‘::json;
— json을 jsonb로 캐스팅하여 중복 키 자동 합치기 (마지막 값이 승인)
SELECT ’{“name”: “Alice”, “name”: “Bob”}‘::json::jsonb;
— 결과: {“name”: “Bob”}
— 외부 데이터에 대한 안전한 삽입 패턴
INSERT INTO user_data (profile)
VALUES (’{“name”: “Alice”, “name”: “Bob”}‘::json::jsonb);
json_object_agg() 집계
키 열에 중복 값을 포함하는 행을 집계할 때 PostgreSQL이 오류 22030을 발생시킵니다.
— 중복 키가 있는 샘플 데이터
CREATE TABLE tags (id INT, k TEXT, v TEXT);
INSERT INTO tags VALUES (1,‘color’,‘red’),(1,‘color’,‘blue’),(1,‘size’,‘M’);
— 오류: 중복 키 값 “color”
SELECT json_object_agg(k, v) FROM tags WHERE id = 1;
— 수정: DISTINCT ON을 사용해Aggregation 전 중복 제거
SELECT json_object_agg(k, v)
FROM (
SELECT DISTINCT ON (k) k, v
FROM tags
WHERE id = 1
ORDER BY k, v
) deduped;
— 대안: 중복 값을 배열로 합치기
SELECT json_object_agg(k, vals)
FROM (
SELECT k, json_agg(v) AS vals
FROM tags
WHERE id = 1
GROUP BY k
) grouped;
외부 데이터 처리 시 json → jsonb 캐스팅을 사용하면 중복 키를 자동으로 해결할 수 있습니다.
json → jsonb 캐스팅을 사용해 외부 데이터를 처리하면 중복 키를 자동으로 해결할 수 있습니다.
Add DISTINCT ON in subqueries before calling json_object_agg().
json_object_agg() 호출 전에 서브쿼리에 DISTINCT ON을 추가하세요.
— Recommended pattern for safe JSON aggregation
WITH deduped AS (
SELECT DISTINCT ON (key_col) key_col, val_col
FROM source_table
ORDER BY key_col, updated_at DESC
)
SELECT json_object_agg(key_col, val_col) FROM deduped;
- 외부 JSON 입력은 저장 전 json → jsonb 캐스팅으로 정규화합니다. 이를 통해 마지막 값을 유지하여 런타임 오류를 방지합니다.
- 집계 전 키를 검증하고 중복 제거하세요. potencially 더러운 데이터 집합에 대해 json_object_agg()를 사용할 때는 CTE 또는 DISTINCT ON / GROUP BY가 포함된 서브쿼리를 사용하십시오.
- 안전한 JSON 집계 패턴
WITH deduped AS (
SELECT DISTINCT ON (key_col) key_col, val_col
FROM source_table
ORDER BY key_col, updated_at DESC
)
SELECT json_object_agg(key_col, val_col) FROM deduped;
22032 (invalid_json_text) — 구문 오류가 있는 JSON; 외부 JSON를 직접 다룰 때 22030과 함께 자주 나타납니다.
23505 (unique_violation) — 고유 인덱스된 열에 중복 값이 있을 때 발생하는 관련 고유 제약 오류입니다.
📖 더 자세한 가이드가 필요하신가요?
oraerror.com — 상세 분석, 추가 SQL 예시 및 예방 팁을 포함합니다.