명령어/DB

[PostgreSQL] JSONB ->, ->>, #>> 로 설정/메타 필드 꺼내기

jykim23 2026. 8. 1. 19:51
반응형

설치·접속: PostgreSQL 설치와 접속

부제: 사용자 설정을 settings jsonb 한 컬럼에 몰아넣었는데, "테마 값만" 또는 "notify.email 값만" 텍스트로 뽑아 화면에 뿌리거나 WHERE에 쓰고 싶을 때

-- ->  는 JSON(jsonb)을 그대로, ->> 는 텍스트로 꺼낸다
SELECT id, settings->'notify' AS notify_json, settings->>'theme' AS theme FROM m4_users;
-- #>> 는 경로 배열로 깊은 값을 한 번에 (텍스트로)
SELECT id, settings#>>'{notify,email}' AS email_on FROM m4_users;
 id |                 notify_json                 | theme 
----+---------------------------------------------+-------
  1 | {"sms": false, "push": true, "email": true} | dark
  2 | {"sms": false, "email": false}              | light
  3 | {"push": false, "email": true}              | dark

 id | email_on 
----+----------
  1 | true
  2 | false
  3 | true

핵심은 화살표 하나 차이다. ->는 결과가 여전히 jsonb라 이어서 또 파고들 수 있고(settings->'notify'->>'email'), ->>text로 끝나 화면 출력이나 비교에 바로 쓴다. 깊은 경로는 ->를 겹치는 대신 #>>'{a,b}' 한 방으로 내려간다. 함정: ->>가 뱉는 건 무조건 text라서, 숫자 비교하려면 (attrs->>'price')::int처럼 캐스팅해야 한다. 안 하면 문자열 정렬로 엉뚱하게 비교된다.

이렇게도 쓴다

WHERE 절에서 ->>로 필터. 문자열 비교라 캐스팅이 필요 없다.

SELECT id, name FROM m4_users WHERE settings->>'plan' = 'pro';

 

숫자 조건은 반드시 캐스팅해서 비교한다. (함정 회피)

SELECT name, (attrs->>'price')::int AS price
FROM m4_products WHERE (attrs->>'price')::int > 1000000;

 

배열 원소는 정수 인덱스로 접근한다 — 첫 태그만 뽑기.

SELECT name, attrs->'tags'->>0 AS first_tag FROM m4_products WHERE attrs ? 'tags';

 

없는 키를 꺼내도 에러가 아니라 NULL이 나온다. (안전하게 넘어감)

SELECT id, settings->>'nickname' AS nickname FROM m4_users;  -- 전부 NULL

 

기본값이 필요하면 COALESCE로 감싼다. (조합: COALESCE)

SELECT id, COALESCE(settings->>'lang','ko') AS lang FROM m4_users;

 

->로 파고든 중간 결과를 다시 꺼내기 — 체이닝. (조합: 화살표 연쇄)

SELECT id, settings->'notify'->>'push' AS push_on FROM m4_users;
반응형