mysql 数组_新特性解读 | 数组范围遍历功能

作者:杨涛涛

资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。

本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

大家都知道,MySQL 从 5.7 开始,增加了新的数据类型:JSON。

JSON 类型的出现,弥补了 MySQL 长期以来相比其他关系型数据库的非标准化特性略势,比如可以用 JSON 来实现类似字典、数组等类型。以及之后大量针对 JSON 类型字串的相关遍历方法与函数。

比如对数组来说,简单的遍历路径为 "$[数组小标]" 或者 "$[*]" 来一次性遍历所有元素。MySQL 8.0 又新增了对于数组元素的范围遍历,比如 "$[m to n]",表示遍历下标为 m 到 n 的元素。

举个例子,以下 JSON 字串(随便找张表 explain format=json 的结果):

# javascriptset @json_str1 = '{  "query_block": {    "table": {      "filtered": "100.00",      "cost_info": {        "eval_cost": "898504.10",        "read_cost": "17457.25",        "prefix_cost": "915961.35",        "data_read_per_join": "137M"      },      "table_name": "t1",      "access_type": "ALL",      "used_columns": [        "id",        "r1",        "r2",        "r3",        "r4",        "r5",        "r6",        "r7",        "r8"      ],      "rows_examined_per_scan": 8985041,      "rows_produced_per_join": 8985041    },    "cost_info": {      "query_cost": "915961.35"    },    "select_id": 1  }}';

其中 key 为 used_columns 对应的值就是一个数组,现在我把这个数据遍历出来,并且生成以下结果:

# javascript["id", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"]["id", "r1", "r2", "r3", "r4", "r5", "r6", "r7"]["id", "r1", "r2", "r3", "r4", "r5", "r6"]["id", "r1", "r2", "r3", "r4", "r5"]["id", "r1", "r2", "r3", "r4"]["id", "r1", "r2", "r3"]["id", "r1", "r2"]["id", "r1"]["id"]

先把这个键对应的值赋给一个变量:

mysql> select json_extract(@json_str1,"$.query_block.table.used_columns") into @json_array1;Query OK, 1 row affected (0.00 sec)

接下来写个传统 PATH 遍历数据的存储过程来实现以上这个结果:

DELIMITER $$USE `ytt`$$DROP PROCEDURE IF EXISTS `sp_print_json_array_sample`$$CREATE DEFINER=`root`@`%` PROCEDURE `sp_print_json_array_sample`(    IN f_str1 JSON    )BEGIN    DECLARE v_tmp_length TINYINT UNSIGNED DEFAULT 0;    DECLARE i TINYINT UNSIGNED DEFAULT 0;    SET v_tmp_length = JSON_LENGTH(f_str1);    SET i = v_tmp_length;    SET @v_tmp_result = f_str1;    DROP TEMPORARY TABLE IF EXISTS tmp;    CREATE TEMPORARY TABLE IF NOT EXISTS tmp(str1 JSON);    WHILE i > 0    DO      SET i = i - 1;      SET @stmt = CONCAT('select json_remove(@v_tmp_result,"$[',i,']") into @v_tmp_result');      INSERT INTO tmp VALUES (@v_tmp_result);      PREPARE s1 FROM @stmt;      EXECUTE s1;      END WHILE;      DROP PREPARE s1;      SET @v_stmt = NULL;      SET @v_tmp_result = NULL;      SELECT * FROM tmp;END$$DELIMITER ;

调用下这个存储过程:

mysql> call sp_print_json_array_sample(@json_array1);+--------------------------------------------------------+| str1                                                   |+--------------------------------------------------------+| ["id", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"] || ["id", "r1", "r2", "r3", "r4", "r5", "r6", "r7"]       || ["id", "r1", "r2", "r3", "r4", "r5", "r6"]             || ["id", "r1", "r2", "r3", "r4", "r5"]                   || ["id", "r1", "r2", "r3", "r4"]                         || ["id", "r1", "r2", "r3"]                               || ["id", "r1", "r2"]                                     || ["id", "r1"]                                           || ["id"]                                                 |+--------------------------------------------------------+9 rows in set (0.01 sec)Query OK, 0 rows affected (0.01 sec)

那在 MySQL 8.0 下,可以直接把这个存储过程给优化掉,简化的写法如下:

DELIMITER $$USE `ytt`$$DROP PROCEDURE IF EXISTS `sp_print_json_array_sample`$$CREATE DEFINER=`root`@`%` PROCEDURE `sp_print_json_array_sample`(    IN f_str1 JSON    )BEGIN    DECLARE v_tmp_length TINYINT UNSIGNED DEFAULT 0;    DECLARE i TINYINT UNSIGNED DEFAULT 0;    SET v_tmp_length = JSON_LENGTH(f_str1);    SET i = v_tmp_length;    DROP TEMPORARY TABLE IF EXISTS tmp;    CREATE TEMPORARY TABLE IF NOT EXISTS tmp(str1 JSON);    WHILE i > 0    DO      SET i = i - 1;      SET @stmt = CONCAT(' insert into tmp select json_extract(''',f_str1,''','' $[ 0 to     ',i,']'') ');      PREPARE s1 FROM @stmt;      EXECUTE s1;    END WHILE;    DROP PREPARE s1;    SET @v_stmt = NULL;    SELECT str1 AS array_result FROM tmp;END$$DELIMITER ;

调用结果一样:

mysql> call sp_print_json_array_sample(@json_array1);+--------------------------------------------------------+| array_result                                           |+--------------------------------------------------------+| ["id", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"] || ["id", "r1", "r2", "r3", "r4", "r5", "r6", "r7"]       || ["id", "r1", "r2", "r3", "r4", "r5", "r6"]             || ["id", "r1", "r2", "r3", "r4", "r5"]                   || ["id", "r1", "r2", "r3", "r4"]                         || ["id", "r1", "r2", "r3"]                               || ["id", "r1", "r2"]                                     || ["id", "r1"]                                           || ["id"]                                                 |+--------------------------------------------------------+9 rows in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)

其中路径 "$[m to n]" , n 也可以是保留字 last,代表最后一个下标,比如:

mysql> select json_extract(@json_array1,'$[0 to last-7]') as result;+--------------+| result       |+--------------+| ["id", "r1"] |+--------------+1 row in set (0.00 sec)

总结

这里简单介绍了 MySQL 8.0 对于 JSON 数组的范围遍历功能,希望大家在开发过程中更加得心应手。


相关推荐:

新特性解读 | MySQL 8.0 语句摘要功能介绍

新特性解读 | GROUPING() 函数用法解析

新特性解读 | InnoDB-Cluster 扫盲-日常运维
f499db770c2dc23e9bacdb2bf0612b69.png

社区近期动态

ebba0527218f5902ba14802fdbfe877b.png 本文关键字:#MySQL8# #数组# #json# 46309824b2ae135ffb794df9dafaa45d.gif  点一下“阅读原文”了解更多资讯
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值