如何在一个SQL UPDATE中多次更新单行的深层嵌套JSON?

时间:2019-07-09 01:47:22

标签: sql json postgresql jsonb

我正在尝试编写查询以更新PostgreSQL数据库中一些深层嵌套的JSON。我仍然要掌握整个JSONB系统。在我的特殊情况下,我试图识别和更新大型JSON捆绑包的多个子部分。特定行可能会深深地包含一个数组。在该数组中,许多元素可能需要根据模式进行更改。

下面是一些代码,用于创建一个示例数据库表,其中仅包含一行,以表达我所面临的问题。这是假数据,因为实际数据是专有数据。

CREATE TABLE "Units" (
  id serial primary key,
  data jsonb
);

INSERT INTO "Units" (data)
VALUES
('
{
  "animals": {
    "mammals": [
      {
        "id": 0,
        "population": 700
      },
      {
        "id": 1
      },
      {
        "id": 2,
        "population": 500
      }
    ],
    "birds": [
      {
        "id": 3,
        "population": 3000
      },
      {
        "id": 4
      }
    ]
  }
}
');

在这种情况下,我想向包含密钥animals -> mammals的{​​{1}}内的每个实体添加密钥。我想添加一个名为population的新密钥,其值应为extinct

这是我已经解决的查询。

false

我发现此查询易于理解,并且一次执行一次脱机修改的性能合理。但是,它有一个致命的缺陷。因为UPDATE "Units" as outside SET data = jsonb_set(outside.data, ('{animals,mammals,' || (inside.ordinality - 1) || ',extinct}')::text[], 'false'::jsonb, true) FROM ( SELECT id, ordinality FROM "Units" INNER JOIN jsonb_array_elements(data->'animals'->'mammals') with ordinality ON id = id WHERE value ? 'population' AND NOT (value ? 'extinct') ) as inside WHERE outside.id = inside.id; 仅在每一行上起作用,所以此查询仅更新找到UPDATE键的两个实体之一。该查询将必须运行两次以更新在第一行中找到的每个实体。现在,假设这是一个更复杂的JSON对象,并且此表中还有很多行。这将是一场噩梦,必须一遍又一遍地更新每个最后一个实体。

如何调整此population,以便它会更新每个匹配行中的每个匹配实体?

这是上面所有内容的DBFiddle

0 个答案:

没有答案