Idéalement, vous n'utilisez pas de documents JSON pour des données structurées et régulières que vous souhaitez manipuler dans une base de données relationnelle. Utilisez plutôt une conception relationnelle normalisée .
JSON est principalement destiné à stocker des documents entiers qui n'ont pas besoin d'être manipulés dans le SGBDR. En relation:
La mise à jour d'une ligne dans Postgres écrit toujours une nouvelle version de la ligne entière . C'est le principe de base du modèle MVCC de Postgres . Du point de vue des performances, peu importe que vous modifiiez une seule donnée dans un objet JSON ou la totalité de celle-ci: une nouvelle version de la ligne doit être écrite.
Ainsi les conseils dans le manuel :
Les données JSON sont soumises aux mêmes considérations de contrôle d'accès concurrentiel que tout autre type de données lorsqu'elles sont stockées dans une table. Bien que le stockage de documents volumineux soit possible, gardez à l'esprit que toute mise à jour acquiert un verrou au niveau de la ligne sur toute la ligne. Envisagez de limiter les documents JSON à une taille gérable afin de réduire les conflits de verrouillage entre les transactions de mise à jour. Idéalement, les documents JSON devraient chacun représenter une donnée atomique que les règles métier dictent ne peut raisonnablement pas être subdivisée en plus petites références qui pourraient être modifiées indépendamment.
L'essentiel: pour modifier quoi que ce soit à l' intérieur d'un objet JSON, vous devez affecter un objet modifié à la colonne. Postgres fournit des moyens limités pour créer et manipuler des json
données en plus de ses capacités de stockage. L'arsenal d'outils s'est considérablement développé avec chaque nouvelle version depuis la version 9.2. Mais le principal demeure: vous devez toujours affecter un objet complètement modifié à la colonne et Postgres écrit toujours une nouvelle version de ligne pour toute mise à jour.
Quelques techniques comment travailler avec les outils de Postgres 9.3 ou version ultérieure:
Cette réponse a attiré autant de votes négatifs que toutes mes autres réponses sur les SO ensemble . Les gens ne semblent pas aimer l'idée: une conception normalisée est supérieure pour les données non dynamiques. Cet excellent article de blog de Craig Ringer explique plus en détail:
Erwin Brandstetter
la source
json
et autresjsonb
. Les deux stockent les données JSON, lejsonb
font sous une forme binaire normalisée qui présente certains avantages (et quelques inconvénients). stackoverflow.com/a/10560761/939860 Aucun des deux types de données n'est bon pour manipuler beaucoup dans la base de données. Aucun type de document n'est. Eh bien, c'est bien pour les petits documents JSON à peine structurés. Mais de gros documents imbriqués seraient une folie de cette façon.Si vous pouvez mettre à niveau vers Postgresql 9.5, la
jsonb_set
commande est disponible, comme d'autres l'ont mentionné.Dans chacune des instructions SQL suivantes, j'ai omis la
where
clause par souci de concision; évidemment, vous voudriez l'ajouter.Mettre à jour le nom:
Remplacez les balises (par opposition à l'ajout ou à la suppression de balises):
Remplacement de la deuxième balise (indexée 0):
Ajouter une balise (
cela fonctionnera tant qu'il y aura moins de 999 balises; changer l'argument 999 en 1000 ou plus génère une erreur. Cela ne semble plus être le cas dans Postgres 9.5.3; un index beaucoup plus grand peut être utilisé) :Supprimez la dernière balise:
Mise à jour complexe (supprimez la dernière balise, insérez une nouvelle balise et modifiez le nom):
Il est important de noter que dans chacun de ces exemples, vous ne mettez pas réellement à jour un seul champ des données JSON. Au lieu de cela, vous créez une version temporaire et modifiée des données et attribuez cette version modifiée à la colonne. En pratique, le résultat devrait être le même, mais en gardant cela à l'esprit, les mises à jour complexes, comme le dernier exemple, devraient être plus compréhensibles.
Dans l'exemple complexe, il existe trois transformations et trois versions temporaires: Premièrement, la dernière balise est supprimée. Ensuite, cette version est transformée en ajoutant une nouvelle balise. Ensuite, la deuxième version est transformée en modifiant le
name
champ. La valeur de ladata
colonne est remplacée par la version finale.la source
jsonb_set
appel externe est la sortie de l'appel interne et que l'entrée de cet appel interne est le résultat dedata #- '{tags,-1}'
. C'est-à-dire les données d'origine avec la dernière balise supprimée.{tags,0}
, cela signifierait "le premier élément du tableautags
", me permettant de donner une nouvelle valeur à cet élément. En utilisant un grand nombre au lieu de 0, au lieu de remplacer un élément existant dans le tableau, il ajoute un nouvel élément au tableau. Cependant, si le tableau contenait en fait plus de 999 999 999 éléments, cela remplacerait le dernier élément au lieu d'en ajouter un nouveau.Cela arrive en 9.5 sous la forme de jsonb_set par Andrew Dunstan basé sur une extension existante jsonbx qui fonctionne avec 9.4
la source
jsonb_build_object()
, carx->key
, ne retourne pas la paire clé-objet, pour remplir dont vous avez besoinjsonb_set(target, path, jsonb_build_object('key',x->key))
.Pour ceux qui rencontrent ce problème et veulent une solution très rapide (et sont bloqués sur 9.4.5 ou une version antérieure), voici ce que j'ai fait:
Création de table de test
Mettre à jour l'instruction pour changer le nom de la propriété jsonb
En fin de compte, la réponse acceptée est correcte en ce sens que vous ne pouvez pas modifier un élément individuel d'un objet jsonb (dans 9.4.5 ou une version antérieure); cependant, vous pouvez convertir l'objet jsonb en une chaîne (:: TEXT), puis manipuler la chaîne et la convertir en l'objet jsonb (:: jsonb).
Il y a deux mises en garde importantes
Cela dit, je suis tombé sur une situation où je devais mettre à jour le schéma du contenu dans les objets jsonb et c'était le moyen le plus simple d'accomplir exactement ce que l'affiche originale demandait.
la source
\u0000
les caractères nuls, l'exemple a montré l'image complète. Merci pour cela!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
Cette question a été posée dans le contexte de postgres 9.4, cependant les nouveaux téléspectateurs venant à cette question doivent savoir que dans postgres 9.5, les opérations de création / mise à jour / suppression du sous-document sur les champs JSONB sont supportées nativement par la base de données, sans avoir besoin d'extension les fonctions.
Voir: JSONB modifiant des opérateurs et des fonctions
la source
mettre à jour l'attribut 'name':
et si vous vouliez supprimer par exemple les attributs 'name' et 'tags':
la source
J'ai écrit une petite fonction pour moi-même qui fonctionne de manière récursive dans Postgres 9.4. J'ai eu le même problème (bien, ils ont résolu une partie de ce mal de tête dans Postgres 9.5). Quoi qu'il en soit, voici la fonction (j'espère que cela fonctionne bien pour vous):
Voici un exemple d'utilisation:
Comme vous pouvez le voir, analysez en profondeur et mettez à jour / ajoutez des valeurs si nécessaire.
la source
jsonb_build_object
été introduit dans la version 9.5Peut-être: UPDATE test SET data = '"mon-autre-nom"' :: json WHERE id = 1;
Cela a fonctionné avec mon cas, où les données sont de type json
la source
Matheus de Oliveira a créé des fonctions pratiques pour les opérations JSON CRUD dans postgresql. Ils peuvent être importés à l'aide de la directive \ i. Notez le fork jsonb des fonctions if jsonb si votre type de données.
9.3 json https://gist.github.com/matheusoliveira/9488951
9.4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
la source