修改存储为 JSON 的列数据

Modify column data stored as JSON

提问人:user1251973 提问时间:11/16/2023 最后编辑:Shadowuser1251973 更新时间:11/16/2023 访问量:42

问:

假设我有 json 列作为JSON_COLUMN,我在其中以以下格式存储数据

表结构:(仅 2 列)

ID - Autoincrement

JSON_COLUMN - Varchar2(1000)

示例数据

ID : 1

JSON_COLUMN :

[
   {
      "Name":"Number",
      "Id":"PhoneNumber",
      "Value":"+393123456789"
   },
   {
      "Name":"Name",
      "Id":"FirstName",
      "Value":"John"
   },
   {
      "Name":"City",
      "Id":"CityID",
      "Value":"NYC"
   }
]

现在我想要更新mariadb的查询,它应该将City的值从NYC替换为CALI

更新表名集 JSON_COLUMN = ???? 不确定在这里保留什么,其中 id = 1;

json mariadb mysql-json

评论

1赞 Bill Karwin 11/16/2023
为什么在JSON中存储数据,而它看起来只是一个相似对象的数组?它应该是第二个表,其中数组项是行,对象字段是列。然后,以您描述的方式更新数据非常容易。
1赞 Bill Karwin 11/16/2023
另外,请具体说明您使用哪个数据库,MySQL还是MariaDB?这些是不同的、不兼容的产品,尤其是在它们的 JSON 实现方面。
0赞 Jeremy Fiel 11/16/2023
JSON_SET 是在 SQL DB 中使用数组时要查找的关键字。PlanetScale昨天刚刚发布了一个非常有趣的视频 youtube.com/watch?v=cDzrY-QW4Ck
0赞 Jeremy Fiel 11/16/2023
MariaDB mariadb.com/kb/en/json_set MySql dev.mysql.com/doc/refman/8.0/en/...

答:

1赞 nbk 11/16/2023 #1

MySQL 和 MariaDB 没有数据类型 varchar2,但 Oracle 有。

使用一个简单的可以帮到你。REPLACE

如果 NYC 一词在您的 json 中只有一个,这就足够了

CREATE TABLE mytable (ID  int  Auto_increment primary key,

JSON_COLUMN  Varchar(1000))
INSERT INTO mytable VALUES (NULL,'[
   {
      "Name":"Number",
      "Id":"PhoneNumber",
      "Value":"+393123456789"
   },
   {
      "Name":"Name",
      "Id":"FirstName",
      "Value":"John"
   },
   {
      "Name":"City",
      "Id":"CityID",
      "Value":"NYC"
   }
]')
UPDATE mytable SET JSON_COLUMN = REPLACE(JSON_COLUMN,'NYC','CALI') WHERE ID = 1
Rows matched: 1  Changed: 1  Warnings: 0
SELECT * FROM mytable
编号 JSON_COLUMN
1 [
{
“name”:“number”, “id”:“PhoneNumber”, “value”:“+393123456789” }, { “name”:“name”, “id”:“FirstName”, “value”:“john” }, { “name”:“city”, “id”:“CityID”,









“value”:“CALI”


}

]

小提琴

如果您知道索引,则可以使用 JSON_REPLACE

UPDATE mytable 
  SET JSON_COLUMN = JSON_REPLACE(JSON_COLUMN,'$[2].Value','CALI') WHERE ID = 1
Rows matched: 1  Changed: 1  Warnings: 0
SELECT JSON_EXTRACT(JSON_COLUMN,'$[2].Value') FROM mytable
JSON_EXTRACT(JSON_COLUMN,'$[2].值')
“卡利”

小提琴

评论

0赞 Bill Karwin 11/16/2023
如果“NYC”出现在 JSON 文档的另一部分,这难道不是错误的事情吗?
0赞 nbk 11/16/2023
@BillKarwin我澄清了这一点,每个用户只有一个 CityID,所以它在 JSON 中应该是唯一的
0赞 user1251973 11/16/2023
非常感谢它按预期工作。但我同意比尔·卡文的观点。如何处理这种情况?
1赞 nbk 11/16/2023
JSON 是保存数据的好方法格式,但是要编辑特定部分,它会变得很快,而且很混乱,所以你应该获取 JSON 并使用其他语言来解析 JSON 并更新它
0赞 nbk 11/16/2023
@user1251973我添加了一个版本,但您现在需要数组中的索引
1赞 Bill Karwin 11/16/2023 #2

下面是一个解决方案,它只更新与数组中的键“Value”相对应的“NYC”。

with cte as (
  select ID, j.* from tablename
  cross join json_table(JSON_COLUMN, '$[*]' columns(
    ord for ordinality, 
    Value varchar(100) path '$.Value')
  ) as j 
  where j.Value = 'NYC'
) 
update tablename cross join cte
set tablename.json_column = json_set(json_column, concat('$[', cte.ord-1, '].Value'), 'CALI')
where cte.id = tablename.id;

这在MySQL 8.0或更高版本中有效,但在MariaDB中无效,因为MariaDB之前不支持通用表表达式。update

演示:https://dbfiddle.uk/tN9Q9-Od


以下是 MariaDB 10.6 或更高版本的解决方案(不适用于旧版本):

update tablename
cross join (
  select ID, j.* from tablename
  cross join json_table(JSON_COLUMN, '$[*]' columns(
    ord for ordinality,
    Value varchar(100) path '$.Value')
  ) as j
  where j.Value = 'NYC'
) as t
set tablename.json_column = json_set(json_column, concat('$[', t.ord-1, '].Value'), 'CALI');

演示:https://dbfiddle.uk/fKHp8BmZ

评论

0赞 user1251973 11/16/2023
我需要mariadb