使用postgresql 9.3我可以选择JSON数据类型的特定字段,但如何使用UPDATE修改它们?我在postgresql文档或网上任何地方都找不到这样的例子。我尝试了一些显而易见的方法:

postgres=# create table test (data json);
CREATE TABLE
postgres=# insert into test (data) values ('{"a":1,"b":2}');
INSERT 0 1
postgres=# select data->'a' from test where data->>'b' = '2';
 ?column?
----------
 1
(1 row)
postgres=# update test set data->'a' = to_json(5) where data->>'b' = '2';
ERROR:  syntax error at or near "->"
LINE 1: update test set data->'a' = to_json(5) where data->>'b' = '2...

当前回答

例如,我的字符串是这样的: {" a1 ":{“a11”:“x”,“a22”:“y”、“a33”:“z”}}

我使用临时表更新jsons,这对于相当小的数据量(<1.000.000)已经足够了。我找到了另一条路,但后来去度假了,就忘了……

所以。查询将是这样的:

with temp_table as (
select 
a.id,
a->'a1'->>'a11' as 'a11',
a->'a1'->>'a22' as 'a22',
a->'a1'->>'a33' as 'a33',
u1.a11updated
from foo a
join table_with_updates u1 on u1.id = a.id)
    update foo a
    set a = ('{"a1": {"a11": "'|| t.a11updated ||'",
        "a22":"'|| t.a22 ||'",
        "a33":"'|| t.a33 ||'"}}')::jsonb
    from temp_table t
    where t.id = a.id;

它与string的关系比json更大,但它是有效的。基本上,它将所有数据拉到临时表中,在用备份的数据插入concat漏洞时创建一个字符串,并将其转换为jsonb。

Json_set可能更有效,但我仍然掌握了它的窍门。当我第一次尝试使用它时,我完全把弦弄乱了……

其他回答

UPDATE test
SET data = data::jsonb - 'a' || '{"a":5}'::jsonb
WHERE data->>'b' = '2'

这似乎在PostgreSQL 9.5上有效

UPDATE table_name SET attrs = jsonb_set(cast(attrs as jsonb), '{key}', '"new_value"', true) WHERE id = 'some_id';

这对我有用,attrs是一个json类型的字段。首先转换为jsonb,然后更新。

or

UPDATE table_name SET attrs = jsonb_set(cast(attrs as jsonb), '{key}', '"new_value"', true) WHERE attrs->>key = 'old_value';

如果您的字段类型是json,下面将为您工作。

UPDATE 
table_name
SET field_name = field_name::jsonb - 'key' || '{"key":new_val}' 
WHERE field_name->>'key' = 'old_value'.

操作符“-”从左操作数中删除键/值对或字符串元素。键/值对根据键值进行匹配。

运算符'||'将两个jsonb值连接成一个新的jsonb值。

因为这些都是jsonb操作符,你只需要将它们类型转换为::jsonb

更多信息:JSON函数和操作符

你可以在这里阅读我的笔记

select * from pg_settings where name = 'deadlock_timeout';
begin;
create temp table a2(data jsonb);
insert into a2 values('{
    "key0": {
        "key01": "2018-05-06T12:36:11.916761+00:00",
        "key02": "DEFAULT_WEB_CONFIGURATION",
    "key1": {
        "key11": "Data System",
        "key12": "<p>Health,<p>my address<p>USA",
        "key13": "*Please refer to main screen labeling"
    }
}}'::jsonb);
commit;

嵌套的jsonb结构更新。可应用于删除。

update a2 set data =
    data::jsonb #-  '{key0, key1, key13}'
        || '{"key13":"screen labeling"}'::jsonb
returning *;

遗憾的是,我没有在文档中找到任何东西,但您可以使用一些变通方法,例如您可以编写一些扩展函数。

例如,在Python中:

CREATE or REPLACE FUNCTION json_update(data json, key text, value json)
returns json
as $$
from json import loads, dumps
if key is None: return data
js = loads(data)
js[key] = value
return dumps(js)
$$ language plpython3u

然后

update test set data=json_update(data, 'a', to_json(5)) where data->>'b' = '2';