CodeGym /행동 /SQL SELF /JSON 오브젝트 합치기와 수정: || 연산자와 jsonb_concat() 함수

JSON 오브젝트 합치기와 수정: || 연산자와 jsonb_concat() 함수

SQL SELF
레벨 34 , 레슨 0
사용 가능

JSON 오브젝트 합치기와 수정: || 연산자와 jsonb_concat() 함수

JSONB가 마치 마법 상자라면, ||jsonb_concat()는 그 상자들을 합치거나 내용물을 바꿔주는 도구야. 실제로 여러 개의 JSON 오브젝트를 합치거나, 한 오브젝트에서 다른 오브젝트로 데이터를 추가하거나, 배열을 하나의 리스트로 합쳐야 할 때가 있지.

예를 들어, 두 개의 JSONB 오브젝트가 있다고 해보자:

{"name": "Alice", "age": 25}

그리고

{"city": "Wonderland", "hobbies": ["reading", "chess"]}

이렇게 만들고 싶을 때:

{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}

또는 두 개의 JSONB 배열을 합치고 싶을 때:

[1, 2, 3]

그리고

[4, 5, 6]

결과가 이렇게 나오게:

[1, 2, 3, 4, 5, 6]

이런 건 전부 ||jsonb_concat()로 할 수 있어. 이제 어떻게 하는지 알아보자.

JSONB 합치기용 || 연산자

|| 연산자는 PostgreSQL에서 두 개의 JSONB 오브젝트나 배열을 합칠 때 써. 간단하고, 빠르고, 쓰기 쉬워. 동작 규칙은 이래:

  • 두 JSONB 오브젝트를 합치면, 결과 오브젝트는 양쪽 오브젝트의 키랑 값을 다 가져와.
  • 키가 겹치면, 오른쪽 오퍼랜드의 값이 왼쪽 값을 덮어써.
  • JSONB 배열을 합치면, 왼쪽 배열과 오른쪽 배열의 요소가 하나의 배열로 합쳐져.

예제 1: 두 JSONB 오브젝트 합치기

SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"city": "Wonderland", "hobbies": ["reading", "chess"]}'::jsonb AS merged_object;

결과:

{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}

예제 2: 키가 겹칠 때 값 업데이트

SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"age": 30, "city": "Wonderland"}'::jsonb AS updated_object;

결과:

{"name": "Alice", "age": 30, "city": "Wonderland"}

여기서 "age" 키의 값이 오른쪽 오브젝트 값으로 바뀐 거 주목해.

예제 3: 배열 합치기

SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS merged_array;

결과:

[1, 2, 3, 4, 5, 6]

JSONB 합치기용 jsonb_concat() 함수

jsonb_concat() 함수는 || 연산자랑 비슷하게 동작하지만, 함수라서 함수 안이나 트리거, 동적 쿼리에서 쓰기 더 편해. 인자로 JSONB 두 개를 받아서 합쳐진 결과를 반환해.

예제: jsonb_concat() 사용

SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combined;

결과:

{"a": 1, "b": 3, "c": 4}

오브젝트와 배열 합치기: 특징과 주의점

키가 겹치는 오브젝트를 합칠 때는 오른쪽 오브젝트의 값이 우선이라는 걸 기억해야 해.

예를 들어:

SELECT '{"key1": "value1"}'::jsonb || '{"key1": "value2"}'::jsonb AS result;

결과:

{"key1": "value2"}

값이 덮어써지는 걸 피하고 싶으면, 각각 다른 키에 저장하거나, 아니면 배열 같은 다른 방법을 써야 해.

그리고 배열은 항상 오른쪽 배열의 요소가 왼쪽 배열 뒤에 붙어서 합쳐져. 예를 들면:

SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS result;

결과:

["a", "b", "c", "d"]

배열 안에 오브젝트가 있어도, 순서는 그대로 유지돼:

SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS result;

결과:

[{"id": 1}, {"id": 2}, {"id": 3}]

실전 예제

유저 프로필 업데이트하기. 예를 들어 users 테이블에 프로필이 JSONB로 저장돼 있다고 하자:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    profile JSONB
);

INSERT INTO users (profile) VALUES ('{"name": "Alice", "age": 25}');

이제 거주 도시를 추가하고 싶을 때:

UPDATE users 
SET profile = profile || '{"city": "Wonderland"}'
WHERE id = 1;

쿼리 결과:

{"name": "Alice", "age": 25, "city": "Wonderland"}

주문 데이터 합치기. 이번엔 orders 테이블이 있다고 해보자:

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    details JSONB
);

INSERT INTO orders (details) VALUES ('{"items": [{"product": "laptop", "quantity": 1}]}');

여기에 상품을 하나 더 추가하고 싶으면:

UPDATE orders
SET details = jsonb_set(
    details,
    '{items}',
    details->'items' || '[{"product": "mouse", "quantity": 2}]'::jsonb
)
WHERE id = 1;

쿼리 결과:

{"items": [{"product": "laptop", "quantity": 1}, {"product": "mouse", "quantity": 2}]}

||jsonb_concat()의 차이

기능적으로 || 연산자랑 jsonb_concat() 함수는 똑같아. 간단한 쿼리엔 ||가 더 짧고 편하고, 함수로 명확하게 호출해야 할 땐 jsonb_concat()가 좋아.

흔한 실수와 예방법

실수: 타입이 안 맞는 걸 합치려고 할 때.

SELECT '{"key": "value"}'::jsonb || '["value"]'::jsonb;

결과:

ERROR:  cannot concatenate jsonb objects and arrays

왼쪽은 오브젝트, 오른쪽은 배열이라 PostgreSQL이 그냥 합칠 수 없어. 둘 다 오브젝트거나, 둘 다 배열이어야 해.

실수: JSONB 쿼리할 때 인덱스 안 쓰는 경우

JSONB 필드 안의 값으로 자주 필터링하는데 인덱스가 없으면, 쿼리가 엄청 느려질 수 있어. 이건 전통적인 의미의 에러는 아니지만, 성능에 큰 영향을 줘. 꼭 GIN 인덱스를 써줘:

CREATE INDEX idx_profile_data ON employees USING gin(profile);
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION