将另一个 key/value 对添加到 POSTGRES 中 jsonb 数组内的所有对象

Add another key/value pair to all objects inside a jsonb array in POSTGRES

我有一个table,我们称它为myTable,结构如下

ID   | data
____________
uuid | jsonb

jsonb字段中的数据是一个结构如下的数组:

[
  {
    "valueA": "500",
    "valueB": "ABC",
  },
  {
    "valueA": "300",
    "valueB": "CDE",
  }
]

我想要做的是通过添加一个 valueC 来转换该数据并将其设置为 valueA,对于 'data' jsonb 数组中的所有对象。

这是我想要的结果:

[
  {
    "valueA": "500",
    "valueB": "ABC",
    "valueC": "500",
  },
  {
    "valueA": "300",
    "valueB": "CDE",
    "valueC": "300",
  }
]

我尝试使用以下查询进行操作:

UPDATE myTable
SET data = d.json_array
FROM (
    SELECT
        jsonb_agg(
                 jsonb_set(elems, '{valueC}', elems->'valueA')
        ) as json_array
    FROM
        myTable,
        jsonb_array_elements(data) elems
) d;

这对 myTable 中的某些条目有效,但对某些人来说它变得疯狂并创建了 300 多个额外的条目,以及我以前拥有的条目。

我在查询中遗漏了什么?

那些FROM 语句是不必要的。您根本不需要 UPDATE 子句 - 您的问题是子查询执行 FROM myTable 然后基本上 self-joins (按笛卡尔积)此子查询结果针对整个 myTable。每行的最后一个(或任何一个)UPDATE 获胜,具体取决于连接顺序,使您的结果不可预测table.

我将移动 SET 子句中的子查询,它只引用正在更新的行的 data

UPDATE myTable
SET data = (
    SELECT jsonb_agg(
        jsonb_set(elems, '{valueC}', elems->'valueA')
    )
    FROM jsonb_array_elements(data) elems
);

或者,您需要在更新的 table 和 FROM 结果之间添加 JOIN 条件:

UPDATE myTable u
SET data = d.json_array
FROM (
    SELECT
        id,
        jsonb_agg(
                 jsonb_set(elems, '{valueC}', elems->'valueA')
        ) as json_array
    FROM
        myTable,
        jsonb_array_elements(data) elems
    GROUP BY
        id
) d
WHERE
    u.id = d.id;