Mise à jour : Avec PostgreSQL 9.5 , il existe des jsonb
fonctionnalités de manipulation dans PostgreSQL lui-même (mais aucune pour json
; les transtypages sont requis pour manipuler les json
valeurs).
Fusion de 2 (ou plusieurs) objets JSON (ou concaténation de tableaux):
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]'
Ainsi, la définition d'une clé simple peut être effectuée en utilisant:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')
Où <key>
doit être une chaîne et <value>
peut être n'importe quel type to_jsonb()
accepté.
Pour définir une valeur profondément dans une hiérarchie JSON , la jsonb_set()
fonction peut être utilisée:
SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
Liste complète des paramètres de jsonb_set()
:
jsonb_set(target jsonb,
path text[],
new_value jsonb,
create_missing boolean default true)
path
peut également contenir des index de tableaux JSON et des entiers négatifs qui apparaissent à partir de la fin des tableaux JSON. Cependant, un index de tableau JSON inexistant mais positif ajoutera l'élément à la fin du tableau:
SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'
Pour l' insertion dans le tableau JSON (tout en préservant toutes les valeurs d'origine) , la jsonb_insert()
fonction peut être utilisée ( en 9.6+; cette fonction uniquement, dans cette section ):
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]}]}'
Liste complète des paramètres de jsonb_insert()
:
jsonb_insert(target jsonb,
path text[],
new_value jsonb,
insert_after boolean default false)
Encore une fois, des nombres entiers négatifs qui apparaissent en path
nombre à partir de la fin des tableaux JSON.
Donc, ex. l'ajout à la fin d'un tableau JSON peut se faire avec:
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
Cependant, cette fonction fonctionne un peu différemment (que jsonb_set()
) lorsque l' path
en target
est la clé d'un objet JSON. Dans ce cas, il n'ajoutera une nouvelle paire clé-valeur pour l'objet JSON que lorsque la clé n'est pas utilisée. S'il est utilisé, il générera une erreur:
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
La suppression d'une clé (ou d'un index) d'un objet JSON (ou d'un tableau) peut se faire avec l' -
opérateur:
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
jsonb '["a",1,"b",2]' - 1 -- will yield jsonb '["a","b",2]'
La suppression, au plus profond d'une hiérarchie JSON, peut se faire avec l' #-
opérateur:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'
Pour 9.4 , vous pouvez utiliser une version modifiée de la réponse d'origine (ci-dessous), mais au lieu d'agréger une chaîne JSON, vous pouvez l'agréger directement dans un objet json avec json_object_agg()
.
Réponse originale : Il est possible (sans plpython ou plv8) également en SQL pur (mais nécessite 9.3+, ne fonctionnera pas avec 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
Modifier :
Une version, qui définit plusieurs clés et valeurs:
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$;
Edit 2 : comme @ErwinBrandstetter l'a noté, ces fonctions ci-dessus fonctionnent comme un soi-disant UPSERT
(met à jour un champ s'il existe, insère s'il n'existe pas). Voici une variante, qui seulement 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$;
Edit 3 : Voici une variante récursive, qui peut définir ( UPSERT
) une valeur de feuille (et utilise la première fonction de cette réponse), située sur un chemin de clé (où les clés ne peuvent se référer qu'à des objets internes, des tableaux internes non pris en charge):
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$;
Mise à jour : les fonctions sont maintenant compactées.
select json_object_set_key((select data from test where data->>'b' = '2'), 'b', 'two');
message d'erreur estERROR: could not determine polymorphic type because input has type "unknown"
UPSERT
, pas d'unUPDATE
. Si la clé n'existe pas encore dans le champ json, elle est ajoutée. Regardez cette question connexe pour un réelUPDATE
: stackoverflow.com/questions/7711432/… (Ceci est pour un type composite, mais le principal est similaire pour json.)$2::text
.Avec 9.5, utilisez jsonb_set-
où body est un type de colonne jsonb.
la source
upper
comme ça:update objects set body=jsonb_set(body, '{name}', upper('"Mary"'), true) where id=1;
il ne reconnaît pas, ou comment puis-je obtenir le même comportement? thxAvec Postgresql 9.5, cela peut être fait en suivant-
OU
Quelqu'un a demandé comment mettre à jour simultanément plusieurs champs de la valeur jsonb. Supposons que nous créons une table:
Ensuite, nous INSÉRONS une ligne expérimentale:
Ensuite, nous METTONS À JOUR la ligne:
Ce qui fait ce qui suit:
Sélection des données:
Aura pour résultat:
Pour mettre à jour le champ à l'intérieur, n'utilisez pas l'opérateur concat
||
. Utilisez jsonb_set à la place. Ce qui n'est pas simple:Utiliser l'opérateur concat pour {c, c1} par exemple:
Supprime {c, c2} et {c, c3}.
Pour plus de puissance, recherchez la puissance dans la documentation des fonctions json postgresql . On pourrait être intéressé par l'
#-
opérateur, lajsonb_set
fonction et aussi lajsonb_insert
fonction.la source
UPDATE users SET profile = profile || '{"lastname":"Washington"}' WHERE profile->>'name' = 'George Washington';
Pour s'appuyer sur les réponses de @ pozs, voici quelques fonctions PostgreSQL supplémentaires qui peuvent être utiles à certains. (Nécessite PostgreSQL 9.3+)
Supprimer par clé: supprime une valeur de la structure JSON par clé.
Suppression récursive par clé: supprime une valeur de la structure JSON par chemin de clé. (nécessite la
json_object_set_key
fonction de @ pozs )Exemples d'utilisation:
la source
Cela semble fonctionner sur PostgreSQL 9.5
la source
Si votre type de champ est json, ce qui suit fonctionnera pour vous.
L'opérateur '-' supprime la paire clé / valeur ou l'élément de chaîne de l'opérande gauche. Les paires clé / valeur sont appariées en fonction de leur valeur clé.
Opérateur '||' concaténer deux valeurs jsonb en une nouvelle valeur jsonb.
Puisque ce sont des opérateurs jsonb, il vous suffit de transtyper en :: jsonb
Plus d'informations: Fonctions et opérateurs JSON
Vous pouvez lire ma note ici
la source
Avec PostgreSQL 9.4, nous avons implémenté la fonction python suivante. Il peut également fonctionner avec PostgreSQL 9.3.
Exemple d'utilisation:
Notez que pour un employeur précédent, j'ai écrit un ensemble de fonctions C pour manipuler les données JSON sous forme de texte (et non comme un
json
oujsonb
type) pour PostgreSQL 7, 8 et 9. Par exemple, extraire des données avecjson_path('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']')
, définir des données avecjson_path_set('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']', '99.87')
et ainsi de suite. Cela a pris environ 3 jours de travail, donc si vous en avez besoin pour fonctionner sur des systèmes hérités et avoir du temps à perdre, cela en vaut la peine. J'imagine que la version C est beaucoup plus rapide que la version python.la source
Cela a fonctionné pour moi lorsque j'ai essayé de mettre à jour un champ de type chaîne.
J'espère que ça aide quelqu'un d'autre!
En supposant que la table nom_table possède une colonne jsonb nommée body et que vous souhaitez modifier body.some_key = 'value'
la source
Même si ce qui suit ne satisfera pas cette demande (la fonction json_object_agg n'est pas disponible dans PostgreSQL 9.3), ce qui suit peut être utile pour tous ceux qui recherchent un || pour PostgreSQL 9.4, tel qu'implémenté dans le prochain PostgreSQL 9.5:
la source
J'ai écrit une petite fonction pour moi qui fonctionne récursivement dans Postgres 9.4. Voici la fonction (j'espère que cela fonctionne bien pour vous):
Voici un exemple d'utilisation:
Comme vous pouvez le voir, analyser en profondeur et mettre à jour / ajouter des valeurs si nécessaire.
la source
Malheureusement, je n'ai rien trouvé dans la documentation, mais vous pouvez utiliser une solution de contournement, par exemple, vous pouvez écrire une fonction étendue.
Par exemple, en Python:
puis
la source
value
nécessitera également unloads
lors de la définition de valeurs non numériques comme des chaînes (js[key] = loads(value)
) - Sinon:select json_update('{"a":"a"}', 'a', to_json('b')); -> {"a": "\"b\""}
L'extrait de code plpython suivant peut être utile.
la source
J'ai trouvé que les réponses précédentes conviennent aux utilisateurs expérimentés de PostgreSQL, d'où ma réponse:
Supposons que vous ayez une table-colonne de type JSONB avec la valeur suivante:
supposons que nous voulons définir une nouvelle valeur dans la ligne:
et placez plutôt la valeur:
nous utilisons la fonction json_set () pour attribuer une nouvelle valeur à key13
les paramètres de jsonb_set ()
dans " cible " - je placerai le nom de la colonne jsonb (c'est la colonne de la table qui est en cours de modification)
" chemin " - est le "chemin des clés json" menant à (et incluant) la clé que nous allons écraser
" new_value " - c'est la nouvelle valeur que nous assignons
dans notre cas, nous voulons mettre à jour la valeur de key13 qui réside sous key1 (key1 -> key13):
d'où la syntaxe du chemin est: '{key1, key13}' (Le chemin était la partie la plus délicate à craquer - parce que les tutoriels sont terribles)
la source
Vous pouvez également incrémenter des clés de manière atomique
jsonb
comme ceci:Clé non définie -> suppose une valeur de départ de 0.
Pour une explication plus détaillée, voir ma réponse ici: https://stackoverflow.com/a/39076637
la source
Pour ceux qui utilisent
mybatis
, voici un exemple de déclaration de mise à jour:Paramètres:
qid
, la clé du champ.value
, est une chaîne json valide, pour la valeur du champ,par exemple convertie de l'objet en chaîne json via
jackson
,la source
Ainsi, par exemple, ma chaîne ressemble à ceci: {"a1": {"a11": "x", "a22": "y", "a33": "z"}}
Je mets à jour jsons en utilisant la table temporaire, ce qui est assez bon pour un assez petit nombre de données (<1.000.000). J'ai trouvé un chemin différent, mais je suis parti en vacances et je l'ai oublié ...
Alors. la requête sera quelque chose comme ceci:
Cela a plus à voir avec la chaîne qu'avec json, mais ça marche. Fondamentalement, il extrait toutes les données dans la table temporaire, crée une chaîne tout en branchant les trous de concaténation avec les données que vous avez sauvegardées et les convertit en jsonb.
Json_set est peut-être plus efficace, mais j'y parviens toujours. La première fois que j'ai essayé de l'utiliser, j'ai complètement foiré la chaîne ...
la source
Si vous effectuez cette requête avec un client de langage de programmation, par exemple à partir de
python pycopg2
, ouNode Postgres
, assurez-vous d'analyser d'abord les nouvelles données vers JSON.Il pourrait facilement ressembler à un dictionnaire python est identique à un objet JSON mais il ne fait pas d'abord json.dumps sur le dictionnaire.
Un simple extrait de 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()
la source