postgresql 使用jsonb_set()的UPDATE只影响嵌套数组中的一个对象

kupeojn6  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(148)

尝试更新jsonb列中嵌套数组的所有元素,但只更新了一个元素。我的查询:

update table_ 
 set value_ = jsonb_set(value_,cte.json_path,cte.namevalue,false) FROM (
select 
 vals2->'ao'->'sc'->'name' as namevalue,
  ('{iProps,'||index1-1||',value,rules,'||index2-1||',ao,sc}')::text[] as json_path
from 
  table_, 
  jsonb_array_elements(value_->'iProps') 
  with ordinality arr1(vals1,index1),
  jsonb_array_elements(vals1->'value'->'rules') 
  with ordinality arr2(vals2,index2)
  ) AS cte;

字符串
查看示例值的演示:

我无法理解为什么这个查询会更新rules数组中的第一个对象:

iProps -> value -> rules -> ao -> sc -> name = "name1"


但不是后来的:

iProps -> value -> rules -> ao -> sc -> name = "name2"
iProps -> value -> rules -> ao -> sc -> name = "name3"

axr492tv

axr492tv1#

说明

UPDATEFROM子句中的子选择返回 * 三 * 行。但是在一个UPDATE命令中,目标表中的每一行只能更新 * 一次 *。结果是您只能看到这三行中的 * 一行 * 的效果。
或者,用手册的话来说:
当使用FROM时,您应该确保连接为每个要修改的行最多生成一个输出行。换句话说,目标行不应该连接到其他表中的多个行。如果是这样,则只有一个连接行将用于更新目标行,但将使用哪一个并不容易预测。
旁白:不要把你的子查询称为“cte”,它不是一个Common Table Expression

正确的UPDATE

UPDATE table_ t
SET    value_ = jsonb_set(value_, '{iProps}', sub2.new_prop, false)
FROM  (
   SELECT id
        , jsonb_agg(jsonb_set(prop, '{value, rules}', new_rules, false)
                    ORDER BY idx1) AS new_prop
   FROM  (
      SELECT t.id, arr1.prop, arr1.idx1
           , jsonb_agg(jsonb_set(rule, '{ao,sc}', rule #> '{ao,sc,name}', false)
                       ORDER BY idx2) AS new_rules
      FROM table_ t
         , jsonb_array_elements(value_->'iProps')       WITH ORDINALITY arr1(prop,idx1)
         , jsonb_array_elements(prop->'value'->'rules') WITH ORDINALITY arr2(rule,idx2)
      GROUP  BY t.id, arr1.prop, arr1.idx1
      ) sub1
   GROUP  BY id
   ) sub2
WHERE t.id = sub2.id;

字符串

  • 小提琴 *

在将每个对象(数组元素)聚合回数组之前,对它们使用jsonb_set()。首先在叶子级别,然后在更深的级别。
我将id作为PRIMARY KEY添加到表中。我们需要一些唯一的列来保持行分离。
添加的ORDER BY可能需要也可能不需要。添加它是为了保证原始订单。
当然,如果您的数据与示例一样有规律,则使用专用列的关系设计可能是一种更简单的选择。

  • 如何对JSONB类型的列执行更新操作

相关问题