如何更新 JSONB 数组 Postgresql 数组对象中的多个值
How to update multiple values in JSONB array Postgresql array object
我下面有一个JSONB数组
[
{"name":"test","age":"21","phone":"6589","town":"54"},
{"name":"test12","age":"67","phone":"6546","town":"54"}
]
现在我想更新 town
、phone
、age
如果 name
是 test。
如何更新 JSONB 数组中的多个值?
下面的查询将为您提供包含 test
个单词的结果。找到这些后,您可以更新其他列中的任何值。
CREATE TABLE TEST2 (
INFO JSON NOT NULL
);
INSERT INTO TEST2 (info)
VALUES('[
{"name":"test","age":"21","phone":"6589","town":"54"},
{"name":"test12","age":"67","phone":"6546","town":"54"},
{"name":"dest147","age":"67","phone":"6546","town":"54"}
]');
SELECT *
FROM TEST2,
json_array_elements(info) elem
WHERE elem ->> 'name' like '%test%';
您可以通过索引每个单独的元素来动态更新它们:
年龄:
WITH s AS
(
SELECT ('{'||idx-1||',age}')::text[] AS path
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsdata,s.path,'"15"',false)
FROM s
对于城镇:
WITH s AS
(
SELECT ('{'||idx-1||',town}')::text[] AS path
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsdata,s.path,'"55"',false)
FROM s
对于phone:
WITH s AS
(
SELECT ('{'||idx-1||',phone}')::text[] AS path
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsdata,s.path,'"1111"',false)
FROM s
或者一次直接:
WITH s AS
(
SELECT ('{'||idx-1||',phone}')::text[] AS path_phone,
('{'||idx-1||',town}')::text[] AS path_town,
('{'||idx-1||',age}')::text[] AS path_age
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsonb_set(jsonb_set(jsdata,
s.path_phone,
'"1111"',
false),
path_town,
'"55"',
false),
s.path_age,
'"20"',
false)
FROM s
此查询较长,但应阐明扩展原始列以进行替换:
with injson as (
select '[
{"name":"test","age":"21","phone":"6589","town":"54"},
{"name":"test12","age":"67","phone":"6546","town":"54"}
]'::jsonb as jarray
), substitution as (
select '{"name": "test", "age": "22", "phone": "6590", "town": "55"}'::jsonb as jnew
), expand as (
select jsonb_array_elements(jarray) as jold
from injson
), cond_update as (
select coalesce(s.jnew, e.jold) as element
from expand e
left join substitution s
on s.jnew->>'name' = e.jold->>'name'
)
select jsonb_agg(element) as result
from cond_update;
result
--------------------------------------------------------------------------------------------------------------------------------
[{"age": "22", "name": "test", "town": "55", "phone": "6590"}, {"age": "67", "name": "test12", "town": "54", "phone": "6546"}]
(1 row)
根据您的 table 描述,它应该看起来像这样:
with substitution as (
select '{"name": "test", "age": "22", "phone": "6590", "town": "55"}'::jsonb as jnew
), expand as (
select id, jsonb_array_elements("caloriesConsumption") as jold
from "calorieTracker"
where id = 1
), cond_update as (
select id, coalesce(s.jnew, e.jold) as element
from expand e
left join substitution s
on s.jnew->>'name' = e.jold->>'name'
)
update "calorieTracker"
set "caloriesConsumption" = cu.element
from cond_update
where cond_update.id = "calorieTracker".id;
我下面有一个JSONB数组
[
{"name":"test","age":"21","phone":"6589","town":"54"},
{"name":"test12","age":"67","phone":"6546","town":"54"}
]
现在我想更新 town
、phone
、age
如果 name
是 test。
如何更新 JSONB 数组中的多个值?
下面的查询将为您提供包含 test
个单词的结果。找到这些后,您可以更新其他列中的任何值。
CREATE TABLE TEST2 (
INFO JSON NOT NULL
);
INSERT INTO TEST2 (info)
VALUES('[
{"name":"test","age":"21","phone":"6589","town":"54"},
{"name":"test12","age":"67","phone":"6546","town":"54"},
{"name":"dest147","age":"67","phone":"6546","town":"54"}
]');
SELECT *
FROM TEST2,
json_array_elements(info) elem
WHERE elem ->> 'name' like '%test%';
您可以通过索引每个单独的元素来动态更新它们:
年龄:
WITH s AS
(
SELECT ('{'||idx-1||',age}')::text[] AS path
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsdata,s.path,'"15"',false)
FROM s
对于城镇:
WITH s AS
(
SELECT ('{'||idx-1||',town}')::text[] AS path
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsdata,s.path,'"55"',false)
FROM s
对于phone:
WITH s AS
(
SELECT ('{'||idx-1||',phone}')::text[] AS path
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsdata,s.path,'"1111"',false)
FROM s
或者一次直接:
WITH s AS
(
SELECT ('{'||idx-1||',phone}')::text[] AS path_phone,
('{'||idx-1||',town}')::text[] AS path_town,
('{'||idx-1||',age}')::text[] AS path_age
FROM tab
CROSS JOIN jsonb_array_elements(jsdata)
WITH ORDINALITY arr(j,idx)
WHERE j->>'name'='test'
)
UPDATE tab
SET jsdata = jsonb_set(jsonb_set(jsonb_set(jsdata,
s.path_phone,
'"1111"',
false),
path_town,
'"55"',
false),
s.path_age,
'"20"',
false)
FROM s
此查询较长,但应阐明扩展原始列以进行替换:
with injson as (
select '[
{"name":"test","age":"21","phone":"6589","town":"54"},
{"name":"test12","age":"67","phone":"6546","town":"54"}
]'::jsonb as jarray
), substitution as (
select '{"name": "test", "age": "22", "phone": "6590", "town": "55"}'::jsonb as jnew
), expand as (
select jsonb_array_elements(jarray) as jold
from injson
), cond_update as (
select coalesce(s.jnew, e.jold) as element
from expand e
left join substitution s
on s.jnew->>'name' = e.jold->>'name'
)
select jsonb_agg(element) as result
from cond_update;
result
--------------------------------------------------------------------------------------------------------------------------------
[{"age": "22", "name": "test", "town": "55", "phone": "6590"}, {"age": "67", "name": "test12", "town": "54", "phone": "6546"}]
(1 row)
根据您的 table 描述,它应该看起来像这样:
with substitution as (
select '{"name": "test", "age": "22", "phone": "6590", "town": "55"}'::jsonb as jnew
), expand as (
select id, jsonb_array_elements("caloriesConsumption") as jold
from "calorieTracker"
where id = 1
), cond_update as (
select id, coalesce(s.jnew, e.jold) as element
from expand e
left join substitution s
on s.jnew->>'name' = e.jold->>'name'
)
update "calorieTracker"
set "caloriesConsumption" = cu.element
from cond_update
where cond_update.id = "calorieTracker".id;