Idealmente, no utiliza documentos JSON para datos estructurados y regulares que desea manipular dentro de una base de datos relacional. Utilice un diseño relacional normalizado en su lugar.
JSON está destinado principalmente a almacenar documentos completos que no necesitan ser manipulados dentro del RDBMS. Relacionado:
Actualizar una fila en Postgres siempre escribe una nueva versión de toda la fila. Ese es el principio básico del modelo MVCC de Postgres . Desde una perspectiva de rendimiento, apenas importa si cambia una sola pieza de datos dentro de un objeto JSON o todo: debe escribirse una nueva versión de la fila.
Por lo tanto, el consejo en el manual :
Los datos JSON están sujetos a las mismas consideraciones de control de concurrencia que cualquier otro tipo de datos cuando se almacenan en una tabla. Aunque es factible almacenar documentos grandes, tenga en cuenta que cualquier actualización adquiere un bloqueo de nivel de fila en toda la fila. Considere limitar los documentos JSON a un tamaño manejable para disminuir la contención de bloqueo entre las transacciones de actualización. Idealmente, los documentos JSON deberían representar cada uno un dato atómico que las reglas de negocio dictan, no se puede subdividir razonablemente en datums más pequeños que se puedan modificar de forma independiente.
La esencia de esto: para modificar cualquier cosa dentro de un objeto JSON, debe asignar un objeto modificado a la columna. Postgres proporciona medios limitados para construir y manipular json
datos además de sus capacidades de almacenamiento. El arsenal de herramientas ha crecido sustancialmente con cada nueva versión desde la versión 9.2. Pero el principio permanece: siempre debe asignar un objeto modificado completo a la columna y Postgres siempre escribe una nueva versión de fila para cualquier actualización.
Algunas técnicas para trabajar con las herramientas de Postgres 9.3 o posterior:
Esta respuesta ha atraído tantos votos negativos como todas mis otras respuestas en SO juntas . A la gente no parece gustarle la idea: un diseño normalizado es superior para los datos no dinámicos. Esta excelente publicación de blog de Craig Ringer explica con más detalle:
Erwin Brandstetter
fuente
json
yjsonb
similares. Ambos almacenan datos JSON,jsonb
lo hacen en una forma binaria normalizada que tiene algunas ventajas (y pocas desventajas). stackoverflow.com/a/10560761/939860 Ninguno de los dos tipos de datos es bueno para manipular mucho dentro de la base de datos. No hay tipo de documento. Bueno, está bien para documentos JSON pequeños, apenas estructurados. Pero los documentos anidados grandes serían una locura de esa manera.Si puede actualizar a Postgresql 9.5, el
jsonb_set
comando está disponible, como han mencionado otros.En cada una de las siguientes declaraciones SQL, he omitido la
where
cláusula de brevedad; obviamente, querrás volver a agregar eso.Nombre de actualización:
Reemplace las etiquetas (en lugar de agregar o quitar etiquetas):
Sustitución de la segunda etiqueta (indexada a 0):
Agregue una etiqueta (
esto funcionará siempre que haya menos de 999 etiquetas; cambiar el argumento 999 a 1000 o superior genera un error. Este ya no parece ser el caso en Postgres 9.5.3; se puede usar un índice mucho mayor) :Eliminar la última etiqueta:
Actualización compleja (elimine la última etiqueta, inserte una nueva etiqueta y cambie el nombre):
Es importante tener en cuenta que en cada uno de estos ejemplos, en realidad no está actualizando un solo campo de los datos JSON. En cambio, está creando una versión temporal y modificada de los datos, y está asignando esa versión modificada a la columna. En la práctica, el resultado debería ser el mismo, pero teniendo esto en cuenta debería hacer actualizaciones complejas, como el último ejemplo, más comprensibles.
En el ejemplo complejo, hay tres transformaciones y tres versiones temporales: Primero, se elimina la última etiqueta. Luego, esa versión se transforma al agregar una nueva etiqueta. A continuación, la segunda versión se transforma cambiando el
name
campo. El valor en ladata
columna se reemplaza con la versión final.fuente
jsonb_set
llamada externa es la salida de la llamada interna, y que la entrada a esa llamada interna es el resultado dedata #- '{tags,-1}'
. Es decir, los datos originales con la última etiqueta eliminada.{tags,0}
, eso significaría "el primer elemento de la matriztags
", lo que me permite dar un nuevo valor a ese elemento. Al usar un número grande en lugar de 0, en lugar de reemplazar un elemento existente en la matriz, agrega un nuevo elemento a la matriz. Sin embargo, si la matriz en realidad tuviera más de 999,999,999 elementos, esto reemplazaría el último elemento en lugar de agregar uno nuevo.Esto viene en 9.5 en forma de jsonb_set por Andrew Dunstan basado en una extensión existente jsonbx que funciona con 9.4
fuente
jsonb_build_object()
, porquex->key
, no devuelve el par clave-objeto, para llenar lo que necesitajsonb_set(target, path, jsonb_build_object('key',x->key))
.Para aquellos que se encuentran con este problema y quieren una solución muy rápida (y están atascados en 9.4.5 o anterior), esto es lo que hice:
Creación de tabla de prueba.
Actualización de la declaración para cambiar el nombre de la propiedad jsonb
En última instancia, la respuesta aceptada es correcta porque no puede modificar una pieza individual de un objeto jsonb (en 9.4.5 o anterior); sin embargo, puede convertir el objeto jsonb en una cadena (:: TEXT) y luego manipular la cadena y volver al objeto jsonb (:: jsonb).
Hay dos advertencias importantes.
Dicho esto, me encontré con una situación en la que tenía que actualizar el esquema para el contenido de los objetos jsonb y esta era la forma más sencilla de lograr exactamente lo que pedía el póster original.
fuente
\u0000
los caracteres nulos, el ejemplo muestra la imagen completa. ¡Gracias por esto!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
Esta pregunta se hizo en el contexto de postgres 9.4, sin embargo, los nuevos espectadores que lleguen a esta pregunta deben tener en cuenta que en postgres 9.5, las operaciones de creación / actualización / eliminación de subdocumentos en campos JSONB son compatibles de forma nativa con la base de datos, sin necesidad de extensión funciones
Ver: JSONB modificando operadores y funciones
fuente
actualizar el atributo 'nombre':
y si desea eliminar, por ejemplo, los atributos 'nombre' y 'etiquetas':
fuente
Escribí una pequeña función para mí que funciona de forma recursiva en Postgres 9.4. Tuve el mismo problema (bueno, resolvieron algo de este dolor de cabeza en Postgres 9.5). De todos modos, aquí está la función (espero que funcione bien para usted):
Aquí está el uso de muestra:
Como puede ver, analice en profundidad y actualice / agregue valores donde sea necesario.
fuente
jsonb_build_object
se introdujo en 9.5Quizás: ACTUALIZAR prueba SET data = '"my-other-name"' :: json WHERE id = 1;
Funcionó con mi caso, donde los datos son de tipo json
fuente
Matheus de Oliveira creó funciones prácticas para las operaciones JSON CRUD en postgresql. Se pueden importar utilizando la directiva \ i. Observe la bifurcación jsonb de las funciones si jsonb si su tipo de datos.
9.3 json https://gist.github.com/matheusoliveira/9488951
9.4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
fuente