A partir deste artigo, tentei atualizar ou excluir a propriedade de uma JSONB
coluna:
CREATE TABLE xxx (id BIGSERIAL, data JSONB);
INSERT INTO xxx(data) VALUES( '{"a":1,"b":2}' );
SELECT * FROM data;
id | data
----+------------------
1 | {"a": 1, "b": 2}
crie a função de atualização:
CREATE FUNCTION jsonb_merge(JSONB, JSONB)
RETURNS JSONB AS $$
WITH json_union AS (
SELECT * FROM JSONB_EACH($1)
UNION ALL
SELECT * FROM JSONB_EACH($2)
) SELECT JSON_OBJECT_AGG(key, value)::JSONB FROM json_union;
$$ LANGUAGE SQL;
teste:
-- replace
UPDATE xxx SET data = jsonb_merge(data,'{"b":3}') WHERE id = 1;
SELECT * FROM xxx;
id | data
----+------------------
1 | {"a": 1, "b": 3}
-- append
UPDATE xxx SET data = jsonb_merge(data,'{"c":4}') WHERE id = 1;
SELECT * FROM xxx;
id | data
----+-------------------------
1 | {"a": 1, "b": 3, "c": 4}
A questão é:
existe alguma desvantagem de usar
JSONB_EACH
(jsonb_merge) em vez deJSONB_EACH_TEXT
(do artigo) neste caso?como modificar o
jsonb_merge
assim se o valor da propriedade do segundo parâmetro fornull
(algo como{"b":null}
) o valor seria apagado?
.
-- remove
UPDATE xxx SET data = jsonb_merge(data,'{"b":null}') WHERE id = 1;
SELECT * FROM xxx;
id | data
----+-----------------
1 | {"a": 1, "c": 4}
Questão 1
Não deve haver desvantagens significativas. Como o
value
é convertido de volta parajsonb
qualquer maneira, eu acho que seria mais eficiente mantê-lo assim o tempo todo.Questão 2
Basta substituir sua função pelo seguinte (apenas a parte
WHERE key NOT IN ...
adicionada):