如何用无键JSON字符串更新MySQL数据库数据?
用无键二维JSON数组更新MySQL数据库的实用方案
嘿,我来帮你搞定这个难题!其实完全不用先把JSON拿到外部解析再循环更新,MySQL 8.0+自带的JSON函数就能直接处理这种无键二维数组,一次性完成批量更新,效率拉满。
先理清楚需求对应的逻辑
你给的JSON是[[匹配值, 字段1值, 字段2值, ...], [...]]的结构:
- 每个子数组的第一个元素是用来匹配目标行的标识(比如你示例里的
800对应表的id字段) - 子数组后面的元素依次对应要更新的各个字段值
步骤1:先模拟你的表结构(方便你对照)
假设你的表叫business_data,字段和你给的更新示例对应:
CREATE TABLE business_data ( id INT PRIMARY KEY, item_name VARCHAR(100), category VARCHAR(10), range_code VARCHAR(20), ref_code VARCHAR(10), status_flag CHAR(1) ); -- 插入测试用的原始数据 INSERT INTO business_data VALUES (800, 'OldData', 'TOT', '200', '', 'I'), (100, 'OldSaleItem', 'OLD', '', '', ''), (200, 'OldTaxFreeItem', 'OLD', '', '', '');
步骤2:核心更新SQL(直接处理JSON)
用JSON_TABLE把二维JSON数组转换成临时关系表,然后关联原表做更新:
UPDATE business_data t -- 把你的JSON数据直接塞进JSON_TABLE的第一个参数里 JOIN JSON_TABLE( '[ ["100", "Salg, avgiftspliktig", "", "", "3000", ""], ["200", "Salg, avgiftsfritt", "", "", "3100", "I"], ["800", "Driftsresultat", "TOT", "300-500", "", "B"] ]', '$[*]' COLUMNS ( -- 子数组第0位是匹配用的id(注意PATH的索引从0开始) match_id INT PATH '$[0]', -- 后面依次对应要更新的字段 new_item_name VARCHAR(100) PATH '$[1]', new_category VARCHAR(10) PATH '$[2]', new_range_code VARCHAR(20) PATH '$[3]', new_ref_code VARCHAR(10) PATH '$[4]', new_status_flag CHAR(1) PATH '$[5]' ) ) j ON t.id = j.match_id SET t.item_name = j.new_item_name, t.category = j.new_category, t.range_code = j.new_range_code, t.ref_code = j.new_ref_code, t.status_flag = j.new_status_flag;
关键细节要注意
- MySQL版本要求:
JSON_TABLE是MySQL 8.0.4及以后才支持的,如果你的版本低于这个,那得用存储过程循环解析(但更推荐升级到8.0+,毕竟JSON处理能力提升太多)。 - 类型匹配:如果你的匹配字段是字符串类型(比如不是
id而是code),记得把match_id的类型改成VARCHAR,避免类型转换报错。 - 空值保留:如果JSON里的空字符串
""不想覆盖原表的非空值,可以用IFNULL做判断,比如:
这样只有当JSON里有有效值时才更新,空字符串就保留原字段的值。SET t.item_name = IFNULL(j.new_item_name, t.item_name) - 批量更新效率:这种方法比外部循环逐个执行
UPDATE快N倍,因为是单次SQL操作,减少了数据库连接和事务的开销。
验证更新结果
执行完上面的SQL后,查询表:
SELECT * FROM business_data;
会得到完全符合你要求的结果:
+-----+---------------------------+----------+-------------+----------+-------------+ | id | item_name | category | range_code | ref_code | status_flag | +-----+---------------------------+----------+-------------+----------+-------------+ | 100 | Salg, avgiftspliktig | | | 3000 | | | 200 | Salg, avgiftsfritt | | | 3100 | I | | 800 | Driftsresultat | TOT | 300-500 | | B | +-----+---------------------------+----------+-------------+----------+-------------+
内容的提问来源于stack exchange,提问作者user2282217
相关产品推荐
相关产品推荐

