MySQL 8 使用 Replace() 或 Regex 更新

MySQL 8 update with Replace() or Regex

如何使用

中的替换或类似正则表达式的方法更新数据
id | jdata
---------------
01 | {"name1":["number","2"]}
02 | {"val1":["number","12"],"val2":["number","22"]}

id | jdata
---------------
01 | {"name1":2 }
02 | {"val1": 12,"val2":22 }

我需要为数字创建一个正确的 json 条目,并用该数组中的数字替换一个数组。列“jdata”可以具有示例中任意数量的相似属性。类似这样的事情会做:

UPDATE table SET jdata = REPLACE(jdata, '["number","%d"]', %d);

两种方式:

  1. 更长、更笨拙的方法,使用 JSON_ARRAY:
UPDATE table1,
(
   SELECT
      id,
      JSON_EXTRACT(jdata, "$.name1[0]") as A,
      JSON_EXTRACT(jdata, "$.name1[1]") as B,
      JSON_EXTRACT(jdata, "$.val1[0]") as C,
      JSON_EXTRACT(jdata, "$.val1[1]") as D,
      JSON_EXTRACT(jdata, "$.val2[0]") as E,
      JSON_EXTRACT(jdata, "$.val2[1]") as F
   FROM table1
) x 
SET jdata = CASE WHEN table1.id=1 THEN JSON_ARRAY("name1",x.B)
                                  ELSE JSON_ARRAY("val1",x.D,"val2",F) END
WHERE x.id=table1.id;
  1. 或使用JSON_REPLACE:
update table1
set jdata = JSON_REPLACE(jdata, "$.name1",JSON_EXTRACT(jdata,"$.name1[1]")) 
where id=1;

update table1
set jdata = JSON_REPLACE(jdata, "$.val1",JSON_EXTRACT(jdata,"$.val1[1]"),
                                "$.val2",JSON_EXTRACT(jdata,"$.val2[1]")) 
where id=2;

参见:DBFIDDLE 两个选项

编辑:为了更深入地了解查询,您可以从下面开始,并从这些内容中创建一条新的 JSON 消息,而无需 number:

WITH RECURSIVE cte1 as (
   select 0 as x
   union all
   select x+1 from cte1 where x<10
   )
select 
   id,
   x,
   JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))) j,
   JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))))) v,
   JSON_UNQUOTE(JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[0]"))) v1,
   JSON_UNQUOTE(JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[1]"))) v2
from table1
cross join cte1
where x<JSON_DEPTH(jdata) 
  and not JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]")) is null
order by id,x;

输出:

id x j v v1 v2
1 0 name1 ["number", "2"] number 2
2 0 val1 ["number", "12"] number 12
2 1 val2 ["number", "22"] number 22

这应该处理 JSON 消息,它还包含 val3val4 等值,直到最大深度现在在 [=17= 中固定为 10 ].

EDIT2:当只需要从JSON消息中删除“数字”时,您也可以重复此更新直到删除所有“数字”标签(您可以在存储过程中重复此操作, 我不打算给你写存储过程)

update 
   table1, 
   ( WITH RECURSIVE cte1 as (
   select 0 as x
   union all
   select x+1 from cte1 where x<10
   ) select * from cte1 )x

set jdata = JSON_REMOVE(table1.jdata, CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[0]"))
where JSON_UNQUOTE(JSON_EXTRACT(jdata,CONCAT("$.",JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(jdata),CONCAT("$[",x,"]"))),"[0]"))) = "number"

一个例子,我 运行 更新了 2 次,在这个 DBFIDDLE