使用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...
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';
你觉得这个解决办法怎么样?
它将添加新值或更新现有值。
编辑:编辑后使其与null和空对象一起工作
Edit2:编辑使它与对象中的对象一起工作…
create or replace function updateJsonb(object1 json, object2 json)
returns jsonb
language plpgsql
as
$$
declare
result jsonb;
tempObj1 text;
tempObj2 text;
begin
tempObj1 = substr(object1::text, 2, length(object1::text) - 2); --remove the first { and last }
tempObj2 = substr(object2::text, 2, length(object2::text) - 2); --remove the first { and last }
IF object1::text != '{}' and object1::text != 'null' and object1::text != '[]' THEN
result = ('{' || tempObj1 || ',' || tempObj2 || '}')::jsonb;
ELSE
result = ('{' || tempObj2 || '}')::jsonb;
END IF;
return result;
end;
$$;
用法:
update table_name
set data = updatejsonb(data, '{"test": "ok"}'::json)
例如,我的字符串是这样的:
{" 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可能更有效,但我仍然掌握了它的窍门。当我第一次尝试使用它时,我完全把弦弄乱了……