2016-08-10 16 views
11

Mam tabelę DB z kolumną jsonb.Postgres jsonb_set wiele aktualizacji kluczy

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

Potrzebuję sposobu na aktualizację kolumny danych. Więc moje wyjście powinno wyglądać następująco:

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

Czy to możliwe ze json_set? Dodałem zapytania jak:

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

jednak, że potrzebny jest sposób, aby dodać nową parę klucz-wartość, jeśli nie istnieje i aktualizacji wartości klucza, jeśli istnieje. Czy można to osiągnąć w pojedynczej kwerendzie?

Odpowiedz

18

documentation says:

|| operator łączy elementy na najwyższym poziomie każdego z operandów. ... Na przykład, jeśli oba operandy są obiektami o wspólnej nazwie pola klucza, wartość pola w wyniku będzie po prostu wartością z prawego argumentu.

Więc przy użyciu przykładowych danych:

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

Dodatkowo, jeśli obiekt, który chcesz edytować nie jest na najwyższym poziomie - wystarczy połączyć konkatenacji i jsonb_set funkcję. Na przykład, jeśli oryginalne dane wygląda

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

następnie

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

Niesamowite, działa to jak urok. Dzięki! Nie mogę go jeszcze głosować, ponieważ nie mam wystarczającej liczby punktów, ale zdecydowanie kciuki w górę. – phpfreak

+0

Jak czytałeś dokumentację postgresową, nie tracąc go całkowicie? –

+1

@MarcoPrins Czy próbowałeś przeczytać dokumentację Oracle? W porównaniu z nim dokumentacja PostgreSQL to literackie arcydzieło: o) – Abelisto

1

Można spróbować tej

Tutaj używamy jsonb concatation operatora || do łączenia dwóch jsonb obiektów

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

proszę odnieść się [jsonb in postgres] (https://www.postgresql.org/docs/9.6/static/functions-json.html) – Paarth