2016-08-10 3 views
11

У меня есть таблица DB с колонкой jsonb.postgres jsonb_set multiple keys update

number | data 
    1 | {"name": "firstName", "city": "toronto", "province": "ON"} 

Мне нужен способ обновления столбца данных. Так что мой вывод должен выглядеть следующим образом:

{"name": "firstName", "city": "ottawa", "province": "ON", "phone": "phonenum", "prefix": "prefixedName"} 

Можно ли с json_set? Я добавил запрос типа:

update table_name set data = jsonb_set(data, '{city}', '"ottawa"') where number = 1; 

Однако, мне нужен способ, чтобы добавить новый ключ-значение, если оно не существует и обновить значение ключа, если он существует. Можно ли добиться этого в одном запросе?

ответ

18

documentation says:

|| оператор конкатенирует элементы на верхнем уровне каждого из своих операндов. ... Например, если оба операнда являются объектами с общим именем поля ключа, значение поля в результате будет просто значением из правого операнда.

Таким образом, используя ваши данные примера:

update table_name set 
    data = data || '{"city": "ottawa", "phone": "phonenum", "prefix": "prefixedName"}' 
where number = 1; 

Кроме того, если объект, который вы хотите редактировать, не на самом высоком уровне - просто объединить конкатенацию и jsonb_set функцию. Например, если исходные данные выглядит

{"location": {"name": "firstName", "city": "toronto", "province": "ON"}} 

затем

... 
data = jsonb_set(data, '{location}', data->'location' || '{"city": "ottawa", "phone": "phonenum", "prefix": "prefixedName"}') 
... 
+0

Удивительно, это работает как шарм. Благодаря! Я пока не могу проголосовать за это, потому что у меня нет достаточного количества очков, но, безусловно, большой палец. – phpfreak

+0

Как вы прочитали документы postgres, не потеряв его полностью –

+1

@MarcoPrins Вы пытались прочитать документацию Oracle? По сравнению с ним документация PostgreSQL является литературным шедевром: o) – Abelisto

1

Вы можете попробовать это

Здесь мы используем jsonb concatation оператора || к Объединить два jsonb объекты

update table_name set data = (select val from (
(select 
CASE WHEN data ? key THEN jsonb_set(data, '{' || key || '}', quote_nullable(updated_value)) 
ELSE 
data || ('{' || quote_ident(key) || ':' || quote_ident(some_value) || '}')::jsonb 
END val 
from json_each_text((select data::json from tbl)) 
CROSS JOIN tbl t 
where key in ('city','phone','prefix') and number=1)) where number=1 
+1

см. [Jsonb in postgres] (https://www.postgresql.org/docs/9.6/static/functions-json.html) – Paarth