Idealmente, você não usa documentos JSON para dados estruturados e regulares que deseja manipular dentro de um banco de dados relacional. Use um design relacional normalizado .
O JSON se destina principalmente a armazenar documentos inteiros que não precisam ser manipulados dentro do RDBMS. Palavras-chave:
A atualização de uma linha no Postgres sempre grava uma nova versão da linha inteira . Esse é o princípio básico do modelo MVCC do Postgres . De uma perspectiva de desempenho, pouco importa se você altera uma única parte dos dados dentro de um objeto JSON ou todos eles: uma nova versão da linha precisa ser gravada.
Assim, o conselho no manual :
Os dados JSON estão sujeitos às mesmas considerações de controle de simultaneidade que qualquer outro tipo de dados quando armazenados em uma tabela. Embora seja possível armazenar documentos grandes, lembre-se de que qualquer atualização adquire um bloqueio no nível da linha em toda a linha. Considere limitar os documentos JSON a um tamanho gerenciável para diminuir a contenção de bloqueio entre as transações de atualização. Idealmente, cada documento JSON deve representar um dado atômico que as regras de negócios determinam, não pode ser razoavelmente subdividido em dados menores que podem ser modificados independentemente.
O essencial: para modificar qualquer coisa dentro de um objeto JSON, você deve atribuir um objeto modificado à coluna. O Postgres fornece meios limitados para criar e manipular json
dados, além de seus recursos de armazenamento. O arsenal de ferramentas cresceu substancialmente a cada novo lançamento desde a versão 9.2. Mas o principal permanece: você sempre deve atribuir um objeto modificado completo à coluna e o Postgres sempre grava uma nova versão de linha para qualquer atualização.
Algumas técnicas de como trabalhar com as ferramentas do Postgres 9.3 ou posterior:
Esta resposta atraiu tantos votos negativos quanto todas as minhas outras respostas no SO juntos . As pessoas não parecem gostar da idéia: um design normalizado é superior para dados não dinâmicos. Este excelente post de Craig Ringer explica em mais detalhes:
json
ejsonb
similares. Ambos armazenam dados JSON,jsonb
em um formato binário normalizado que possui algumas vantagens (e poucas desvantagens). stackoverflow.com/a/10560761/939860 Nenhum tipo de dado é bom para manipular muito dentro do banco de dados. Nenhum tipo de documento é. Bem, tudo bem para documentos JSON pequenos e pouco estruturados. Mas documentos grandes e aninhados seriam uma loucura.Se você pode atualizar para o Postgresql 9.5, o
jsonb_set
comando está disponível, como outros já mencionaram.Em cada uma das seguintes instruções SQL, omiti a
where
cláusula por brevidade; obviamente, você gostaria de adicionar isso de volta.Nome da atualização:
Substitua as tags (em vez de adicionar ou remover tags):
Substituindo a segunda tag (indexada 0):
Anexar uma tag (
isso funcionará desde que haja menos de 999 tags; a alteração do argumento 999 para 1000 ou acima gera um erro. Isso não parece mais ser o caso no Postgres 9.5.3; um índice muito maior pode ser usado) :Remova a última tag:
Atualização complexa (exclua a última tag, insira uma nova tag e altere o nome):
É importante observar que em cada um desses exemplos, na verdade, você não está atualizando um único campo dos dados JSON. Em vez disso, você está criando uma versão modificada temporária dos dados e atribuindo essa versão modificada de volta à coluna. Na prática, o resultado deve ser o mesmo, mas manter isso em mente deve tornar as atualizações complexas, como o último exemplo, mais compreensíveis.
No exemplo complexo, há três transformações e três versões temporárias: Primeiro, a última tag é removida. Em seguida, essa versão é transformada adicionando uma nova tag. Em seguida, a segunda versão é transformada alterando o
name
campo. O valor nadata
coluna é substituído pela versão final.fonte
jsonb_set
chamada externa é a saída da chamada interna e que a entrada para essa chamada interna é o resultado dedata #- '{tags,-1}'
. Ou seja, os dados originais com a última tag removida.{tags,0}
, isso significaria "o primeiro elemento da matriztags
", permitindo que eu desse um novo valor a esse elemento. Usando um número grande em vez de 0, em vez de substituir um elemento existente na matriz, ele adiciona um novo elemento à matriz. No entanto, se a matriz tivesse realmente mais de 999.999.999 elementos, isso substituiria o último elemento em vez de adicionar um novo.Isso está chegando na versão 9.5, na forma de jsonb_set, por Andrew Dunstan, com base em uma extensão existente, jsonbx, que funciona com a 9.4
fonte
jsonb_build_object()
, porquex->key
, não retorna o par de chave-objeto, para preencher o necessáriojsonb_set(target, path, jsonb_build_object('key',x->key))
.Para aqueles que se deparam com esse problema e desejam uma correção muito rápida (e estão presos no 9.4.5 ou anterior), aqui está o que eu fiz:
Criação da tabela de teste
Instrução de atualização para alterar o nome da propriedade jsonb
Por fim, a resposta aceita está correta, pois você não pode modificar uma parte individual de um objeto jsonb (na 9.4.5 ou anterior); no entanto, você pode converter o objeto jsonb em uma string (:: TEXT) e, em seguida, manipular a string e converter de volta no objeto jsonb (:: jsonb).
Existem duas advertências importantes
Com isso dito, me deparei com uma situação em que eu tinha que atualizar o esquema para o conteúdo nos objetos jsonb e essa era a maneira mais simples de realizar exatamente o que o pôster original estava pedindo.
fonte
\u0000
os caracteres nulos, o exemplo mostrou a imagem completa. Obrigado por isso!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
Essa pergunta foi feita no contexto do postgres 9.4, no entanto, os novos visualizadores que chegarem a essa pergunta devem estar cientes de que no postgres 9.5, o sub-documento Criar / Atualizar / Excluir operações nos campos JSONB é suportado nativamente pelo banco de dados, sem a necessidade de extensão funções.
Consulte: JSONB modificando operadores e funções
fonte
atualize o atributo 'name':
e se você deseja remover, por exemplo, os atributos 'name' e 'tags':
fonte
Escrevi para mim uma pequena função que funciona recursivamente no Postgres 9.4. Eu tive o mesmo problema (bom que eles resolveram um pouco dessa dor de cabeça no Postgres 9.5). Enfim, aqui está a função (espero que funcione bem para você):
Aqui está o uso da amostra:
Como você pode ver, analise no fundo e atualize / adicione valores sempre que necessário.
fonte
jsonb_build_object
foi introduzido no 9.5Talvez: UPDATE test SET data = '"meu-outro-nome"' :: json WHERE id = 1;
Funcionou com o meu caso, em que dados são do tipo json
fonte
Matheus de Oliveira criou funções úteis para operações JSON CRUD no postgresql. Eles podem ser importados usando a diretiva \ i. Observe o fork jsonb das funções se jsonb se seu tipo de dados.
9.3 json https://gist.github.com/matheusoliveira/9488951
9.4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
fonte