繁体   English   中英

如何更新 JSONB 数组 Postgresql 数组 object 中的多个值

[英]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"}
]

现在我想更新townphoneage ,如果name测试 如何更新 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

对于电话

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)

根据您的表的描述,它应该如下所示:

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM