【问题标题】:Update json values by their key name通过键名更新 json 值
【发布时间】:2021-06-16 01:08:20
【问题描述】:

背景

我有一个带有 json 字段的 MySQL 表。该字段存储一个 json 对象数组。 顺序并不总是相同的,所以我需要获取更新操作的键的路径。


Entity | ID, jsonField |

Entity | 1,  [{clazz:'health', hp:'100'},{...},{...}] // Health the first index
Entity | 2,  [{...},{...},{clazz:'health', hp:'25'}] // Health at the last index

问题

如何获取每个实体的 .hp 字段的路径以更新其值?或者......更珍贵一点,我们如何在每个实体 jsonField 数组中将 .hp 字段设置为,比如说 100,无论其位置如何?

【问题讨论】:

  • 你有一个 JSON 对象数组,每个对象都有相同的字段,clazzhp?为什么不将这些作为行存储在第二个表中,带有 clazz varchar 列和 hp int 列?然后,几乎可以轻松地用它们做任何你想做的事情。
  • @BillKarwin 谢谢,但那是不可能的。每个实体在该字段内都有 0-n 个不同的未知对象……这就是动态结构在这里很重要的原因。
  • 使用正则表达式——这样会更简单快捷。
  • @Akina 谢谢,我要去调查他们!你能举个例子吗? ^^
  • 请提供 CREATE TABLE 脚本和 INSERT INTO 一些示例数据(3-5 行),并显示所需的输出。

标签: mysql sql json


【解决方案1】:

您可以使用递归 CTE 查找数组中 hp 键的索引(如果存在),然后使用该结果进行更新:

with recursive cte(id, js, ind, f) as (
   select e.id, e.jsonfield, 0, json_extract(e.jsonfield, '$[0].hp') is not null from entities e
   union all
   select c.id, c.js, c.ind+1, json_extract(c.js, concat('$[', c.ind+1, '].hp')) is not null from cte c where not c.f and c.ind+1 < json_length(c.js)
),
inds(id, ind) as (select id, ind from cte where f)
update entities e join inds i on e.id = i.id set e.jsonfield = json_set(e.jsonfield, concat('$[', i.ind, '].hp'), '100');
select * from entites;

输出:

entity id jsonfield
entity 1 [{"hp": "100", "clazz": "health"}, {"x": "1"}, {"y": "2"}]
entity 2 [{"x": "1"}, {"y": "2"}, {"hp": "100", "clazz": "health"}]

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 2011-01-06
    相关资源
    最近更新 更多