Aktualizacja : w PostgreSQL 9.5 jest kilkajsonb
funkcje manipulacji w samym PostgreSQL (ale żadne z nich json
; rzutowanie jest wymagane do manipulowania json
wartościami).
Scalanie 2 (lub więcej) obiektów JSON (lub konkatenacja tablic):
SELECT jsonb '{"a":1}' || jsonb '{"b":2}', -- will yield jsonb '{"a":1,"b":2}'
jsonb '["a",1]' || jsonb '["b",2]' -- will yield jsonb '["a",1,"b",2]'
Tak więc ustawienie prostego klucza można wykonać za pomocą:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')
Gdzie <key>
powinien być ciąg, oraz<value>
może być dowolnym typem to_jsonb()
.
Do ustawiania głęboką wartość w hierarchii JSON The jsonb_set()
funkcja może być używana:
SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
Pełna lista parametrów jsonb_set()
:
jsonb_set(target jsonb,
path text[],
new_value jsonb,
create_missing boolean default true)
path
może również zawierać indeksy tablic JSON i wyświetlane tam ujemne liczby całkowite liczą się od końca tablic JSON. Jednak nieistniejący, ale dodatni indeks tablicy JSON doda element na końcu tablicy:
SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'
W przypadku wstawienia w JSON tablicy (przy zachowaniu wszystkich wartości pierwotnych) The jsonb_insert()
funkcja może być stosowany ( w 9.6+; funkcję jedynie w tej części )
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2')
-- will yield jsonb '{"a":[null,{"b":[2,1]}]}', and
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2', true)
-- will yield jsonb '{"a":[null,{"b":[1,2]}]}'
Pełna lista parametrów jsonb_insert()
:
jsonb_insert(target jsonb,
path text[],
new_value jsonb,
insert_after boolean default false)
Ponownie, ujemne liczby całkowite, które pojawiają się w path
liczeniu od końca tablic JSON.
Na przykład dołączanie na końcu tablicy JSON można wykonać za pomocą:
SELECT jsonb_insert('{"a":[null,{"b":[1,2]}]}', '{a,1,b,-1}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}', and
Jednak ta funkcja działa nieco inaczej (niż jsonb_set()
), gdy path
in target
jest kluczem obiektu JSON. W takim przypadku doda nową parę klucz-wartość dla obiektu JSON tylko wtedy, gdy klucz nie zostanie użyty. Jeśli zostanie użyty, zgłosi błąd:
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,c}', jsonb '[2]')
-- will yield jsonb '{"a":[null,{"b":[1],"c":[2]}]}', but
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b}', jsonb '[2]')
-- will raise SQLSTATE 22023 (invalid_parameter_value): cannot replace existing key
Usunięcie klucza (lub indeksu) z obiektu JSON (lub z tablicy) można wykonać za pomocą -
operatora:
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
jsonb '["a",1,"b",2]' - 1 -- will yield jsonb '["a","b",2]'
Usunięcie z głębokiej hierarchii JSON można wykonać za pomocą #-
operatora:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'
W wersji 9.4 możesz użyć zmodyfikowanej wersji oryginalnej odpowiedzi (poniżej), ale zamiast agregować ciąg JSON, możesz agregować bezpośrednio w obiekt json json_object_agg()
.
Oryginalna odpowiedź : jest to możliwe (bez plpython lub plv8) również w czystym SQL (ale wymaga wersji 9.3+, nie będzie działać z wersją 9.2)
CREATE OR REPLACE FUNCTION "json_object_set_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields"
$function$;
SQLFiddle
Edytuj :
Wersja, która ustawia wiele kluczy i wartości:
CREATE OR REPLACE FUNCTION "json_object_set_keys"(
"json" json,
"keys_to_set" TEXT[],
"values_to_set" anyarray
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> ALL ("keys_to_set")
UNION ALL
SELECT DISTINCT ON ("keys_to_set"["index"])
"keys_to_set"["index"],
CASE
WHEN "values_to_set"["index"] IS NULL THEN 'null'::json
ELSE to_json("values_to_set"["index"])
END
FROM generate_subscripts("keys_to_set", 1) AS "keys"("index")
JOIN generate_subscripts("values_to_set", 1) AS "values"("index")
USING ("index")) AS "fields"
$function$;
Edycja 2 : jak zauważył @ErwinBrandstetter , powyższe funkcje działają jak tzw. UPSERT
(Aktualizuje pole, jeśli istnieje, wstawia, jeśli nie istnieje). Oto wariant, który tylko UPDATE
:
CREATE OR REPLACE FUNCTION "json_object_update_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE
WHEN ("json" -> "key_to_set") IS NULL THEN "json"
ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields")::json
END
$function$;
Edycja 3 : Oto wariant rekurencyjny, w którym można ustawić ( UPSERT
) wartość liścia (i używa pierwszej funkcji z tej odpowiedzi), zlokalizowaną przy ścieżce klucza (gdzie klucze mogą odnosić się tylko do wewnętrznych obiektów, wewnętrzne tablice nie są obsługiwane):
CREATE OR REPLACE FUNCTION "json_object_set_path"(
"json" json,
"key_path" TEXT[],
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE COALESCE(array_length("key_path", 1), 0)
WHEN 0 THEN to_json("value_to_set")
WHEN 1 THEN "json_object_set_key"("json", "key_path"[l], "value_to_set")
ELSE "json_object_set_key"(
"json",
"key_path"[l],
"json_object_set_path"(
COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
"key_path"[l+1:u],
"value_to_set"
)
)
END
FROM array_lower("key_path", 1) l,
array_upper("key_path", 1) u
$function$;
Aktualizacja : funkcje są teraz skompaktowane.
select json_object_set_key((select data from test where data->>'b' = '2'), 'b', 'two');
wyświetlenia komunikatu o błędzie widzę błądERROR: could not determine polymorphic type because input has type "unknown"
UPSERT
, a nie anUPDATE
. Jeśli klucz nie istnieje jeszcze w polu json, zostanie dodany. Spójrz na to pokrewne pytanie, aby uzyskać rzeczywisteUPDATE
: stackoverflow.com/questions/7711432/... (To jest dla typu złożonego, ale zasada jest podobna dla json.)$2::text
.W wersji 9.5 użyj jsonb_set-
gdzie body jest typem kolumny jsonb.
źródło
upper
:update objects set body=jsonb_set(body, '{name}', upper('"Mary"'), true) where id=1;
nie rozpoznaje lub jak mogę osiągnąć to samo zachowanie? dziękiW Postgresql 9.5 można to zrobić, postępując zgodnie z:
LUB
Ktoś zapytał, jak zaktualizować wiele pól w wartości jsonb jednocześnie. Załóżmy, że tworzymy tabelę:
Następnie WKŁADAMY wiersz eksperymentalny:
Następnie AKTUALIZUJEMY wiersz:
Co powoduje:
Wybieranie danych:
Spowoduje to:
Aby zaktualizować pole wewnątrz, nie używaj operatora concat
||
. Zamiast tego użyj jsonb_set. Co nie jest proste:Na przykład za pomocą operatora concat dla {c, c1}:
Usunie {c, c2} i {c, c3}.
Aby uzyskać więcej mocy, poszukaj mocy w dokumentacji funkcji jg postgresql . Można być zainteresowanym
#-
operatorem,jsonb_set
funkcją, a takżejsonb_insert
funkcją.źródło
UPDATE users SET profile = profile || '{"lastname":"Washington"}' WHERE profile->>'name' = 'George Washington';
Aby skorzystać z odpowiedzi @ pozs, oto kilka innych funkcji PostgreSQL, które mogą być przydatne dla niektórych. (Wymaga PostgreSQL 9.3+)
Usuń według klucza: Usuwa wartość ze struktury JSON według klucza.
Rekurencyjne usuwanie według klucza: Usuwa wartość ze struktury JSON według ścieżki klucza. (wymaga @ pozs
json_object_set_key
)Przykłady użycia:
źródło
Wygląda na to, że działa na PostgreSQL 9.5
źródło
Jeśli typ pola to Json, następujące opcje będą działać dla Ciebie.
Operator ”-„ usuwa parę klucz / wartość lub element łańcucha z lewego operandu. Pary klucz / wartość są dobierane na podstawie ich wartości klucza.
Operator „||” połącz dwie wartości jsonb w nową wartość jsonb.
Ponieważ są to operatorzy jsonb, wystarczy tylko typecast na :: jsonb
Więcej informacji: Funkcje i operatory JSON
Możesz przeczytać moją notatkę tutaj
źródło
W PostgreSQL 9.4 zaimplementowaliśmy następującą funkcję python. Może także współpracować z PostgreSQL 9.3.
Przykładowe użycie:
Zauważ, że dla poprzedniego pracodawcy napisałem zestaw funkcji C do manipulowania danymi JSON jako tekstem (nie jako a
json
lubjsonb
typem) dla PostgreSQL 7, 8 i 9. Na przykład wyodrębnianie danych za pomocąjson_path('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']')
, ustawianie danych za pomocąjson_path_set('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']', '99.87')
i tak dalej. Zajęło to około 3 dni pracy, więc jeśli potrzebujesz go uruchomić na starszych systemach i mieć czas do stracenia, być może warto. Wyobrażam sobie, że wersja C jest znacznie szybsza niż wersja Python.źródło
Mimo że poniższe polecenia nie spełnią tego żądania (funkcja json_object_agg nie jest dostępna w PostgreSQL 9.3), poniższe informacje mogą być przydatne dla każdego, kto szuka || operator PostgreSQL 9.4, zaimplementowany w nadchodzącym PostgreSQL 9.5:
źródło
Napisałem dla siebie małą funkcję, która działa rekurencyjnie w Postgres 9.4. Oto funkcja (mam nadzieję, że będzie dla ciebie dobra):
Oto przykładowe użycie:
Jak widzisz, analizuj głęboko i aktualizuj / dodawaj wartości w razie potrzeby.
źródło
To działało dla mnie, gdy próbowałem zaktualizować pole typu ciągu.
Mam nadzieję, że pomoże to komuś innemu!
Zakładając, że tabela nazwa_tabeli ma kolumnę jsonb o nazwie body i chcesz zmienić body.some_key = 'wartość'
źródło
Niestety nie znalazłem niczego w dokumentacji, ale możesz skorzystać z obejścia, na przykład możesz napisać jakąś rozszerzoną funkcję.
Na przykład w Pythonie:
i wtedy
źródło
value
Będzie również wymagaćloads
przy ustalaniu wartości liczbowych innych niż jak struny (js[key] = loads(value)
) - W przeciwnym razie:select json_update('{"a":"a"}', 'a', to_json('b')); -> {"a": "\"b\""}
Przyda się następujący fragment kodu plpython.
źródło
Odkryłem, że poprzednie odpowiedzi są odpowiednie dla doświadczonych użytkowników PostgreSQL, stąd moja odpowiedź:
Załóżmy, że masz kolumnę tabeli typu JSONB o następującej wartości:
Załóżmy, że chcemy ustawić nową wartość w wierszu:
i zamiast tego wstaw wartość:
używamy funkcji json_set (), aby przypisać nową wartość do key13
parametry do jsonb_set ()
w ” celu ” - wstawię nazwę kolumny jsonb (jest to kolumna tabeli, która jest modyfikowana)
„ ścieżka ” - to „ścieżka kluczy Jsona” prowadząca do (i włącznie) klucza, który zamierzamy zastąpić
„ nowa_wartość ” - to nowa wartość, którą przypisujemy
w naszym przypadku chcemy zaktualizować wartość klucza 13, który znajduje się pod kluczem 1 (klucz1 -> klucz13):
stąd składnia ścieżki to: „{klucz1, klucz13}” (Ścieżka była najtrudniejszą częścią do złamania - ponieważ samouczki są okropne)
źródło
Możesz także zwiększać liczbę atomów w
jsonb
następujący sposób:Niezdefiniowany klucz -> zakłada wartość początkową 0.
Aby uzyskać bardziej szczegółowe wyjaśnienia, zobacz moją odpowiedź tutaj: https://stackoverflow.com/a/39076637
źródło
Dla tych, którzy korzystają
mybatis
, oto przykładowa instrukcja aktualizacji:Params:
qid
, klucz do pola.value
, jest prawidłowym łańcuchem json, dla wartości pola,np. konwertowany z obiektu na łańcuch json przez
jackson
,źródło
Na przykład mój ciąg wygląda następująco: {„a1”: {„a11”: „x”, „a22”: „y”, „a33”: „z”}}
Aktualizuję jsons za pomocą tabeli temp, która jest wystarczająca dla dość małej ilości danych (<1.000.000). Znalazłem inną drogę, ale potem pojechałem na wakacje i zapomniałem ...
Więc. zapytanie będzie wyglądać mniej więcej tak:
Ma więcej wspólnego z łańcuchem niż z Jsonem, ale działa. Zasadniczo ciągnie wszystkie dane do tabeli tymczasowej, tworzy ciąg, zaślepiając otwory konkat z danymi, których kopię zapasową utworzono, i konwertuje je do formatu jsonb.
Json_set może być bardziej wydajny, ale wciąż go rozumiem. Za pierwszym razem, gdy próbowałem go użyć, całkowicie zepsułem strunę ...
źródło
Jeśli wykonujesz to zapytanie za pomocą klienta języka programowania, np. Z
python pycopg2
lubNode Postgres
, Upewnij się, że najpierw parsujesz nowe dane do JSON.Może łatwo wyglądać, jakby słownik Pythona był taki sam jak obiekt JSON, ale najpierw nie wykonuje zrzutów json.d w słowniku.
Prosty fragment kodu python:
def change_destination(self,parcel_id,destlatlng): query="UPDATE parcels SET destlatlng = '{}' WHERE parcel_id ={};".format(json.dumps(destlatlng), parcel_id) self.cursor.execute(query2) self.connection.commit()
źródło