MySQL 中查询 VARCHAR 类型 JSON 数据的

在数据库设计中,有时我们会将 JSON 数据存储在 VARCHAR 或 TEXT 类型字段中。这种方式虽然灵活,但在查询时需要特别注意。本文将详细介绍如何在 MySQL 中有效查询存储为 VARCHAR 类型的 JSON 数据。

一、问题背景

当 JSON 数据存储在 VARCHAR 列中时,常见的数据格式如下:

[{"id":"1905555466980773889","hasPermission":true},{"id":"1905547884060835841","hasPermission":false}
]

我们需要查询这个 JSON 数组中是否包含特定 ID 的对象。

二、MySQL JSON 函数

MySQL 5.7+ 版本提供了丰富的 JSON 处理函数,即使数据类型是 VARCHAR,只要内容是有效的 JSON,我们仍然可以使用这些函数:

2.1 常用 JSON 函数

  • JSON_CONTAINS(target, candidate[, path]): 检查 JSON 文档是否包含特定值
  • JSON_EXTRACT(json_doc, path): 从 JSON 文档中提取值
  • JSON_OBJECT(key, val[, key, val]...): 创建 JSON 对象
  • JSON_ARRAY(val[, val]...): 创建 JSON 数组
  • JSON_VALID(json_doc): 验证字符串是否为有效的 JSON

三、查询示例

3.1 基本查询

查询 JSON 数组中包含特定 ID 的记录:

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

3.2 查询多个 ID

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND (JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'))OR JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905547884060835841')));

3.3 使用 JSON_OVERLAPS (MySQL 8.0+)

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_OVERLAPS(app_ids, JSON_ARRAY(JSON_OBJECT('id', '1905555466980773889'),JSON_OBJECT('id', '1905547884060835841')));

3.4 查询特定权限的记录

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889', 'hasPermission', true));

四、避免常见错误

4.1 空值处理

JSON_CONTAINS 函数在处理 NULL 或空字符串时会报错,所以需要先排除这些情况:

-- 错误做法
SELECT * FROM sys_user WHERE JSON_CONTAINS(app_ids, JSON_OBJECT('id', '123'));-- 正确做法
SELECT * FROM sys_user 
WHERE app_ids IS NOT NULL AND app_ids != '' AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '123'));

4.2 JSON 格式匹配

确保 JSON_CONTAINS 的第二个参数结构与目标 JSON 中的结构匹配:

-- 错误做法 (直接传入 ID 字符串)
SELECT * FROM sys_user WHERE JSON_CONTAINS(app_ids, '"1905555466980773889"');-- 正确做法 (创建与数组元素匹配的对象)
SELECT * FROM sys_user WHERE JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

4.3 确保 JSON 有效性

添加 JSON_VALID 检查确保字段内容是有效的 JSON:

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_VALID(app_ids) = 1AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

五、在 MyBatis Plus 中的应用

5.1 基本查询

LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.isNotNull(SysUser::getAppIds).ne(SysUser::getAppIds, "").apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905555466980773889");List<SysUser> userList = sysUserMapper.selectList(queryWrapper);

5.2 多条件查询

QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
queryWrapper.isNotNull("app_ids").ne("app_ids", "").apply("JSON_VALID(app_ids) = 1").apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905555466980773889");// 如果还要根据权限过滤
queryWrapper.apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}, 'hasPermission', {1}))", "1905555466980773889", true);

5.3 查询多个 ID

LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.isNotNull(SysUser::getAppIds).ne(SysUser::getAppIds, "").and(w -> w.apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905555466980773889").or().apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905547884060835841"));List<SysUser> userList = sysUserMapper.selectList(queryWrapper);

六、性能优化建议

  1. 考虑使用 JSON 类型:如果您的 MySQL 版本是 5.7+,考虑使用原生 JSON 类型代替 VARCHAR,这样可以获得更好的性能和功能支持。

  2. 添加索引:虽然无法直接为 JSON 内容创建索引,但可以使用生成的列和函数索引:

    ALTER TABLE sys_user ADD COLUMN app_id_extracted JSON GENERATED ALWAYS AS (JSON_EXTRACT(app_ids, '$[*].id')) VIRTUAL;ALTER TABLE sys_user ADD INDEX idx_app_id_extracted (app_id_extracted);
    
  3. 定期维护:对于大表,定期 OPTIMIZE TABLE 有助于维护性能。

七、总结

在 MySQL 中查询 VARCHAR 类型的 JSON 数据时,关键是:

  1. 使用 JSON_CONTAINS 函数并构造正确的 JSON 结构进行匹配
  2. 处理好 NULL 和空字符串
  3. 验证 JSON 有效性
  4. 在 MyBatis Plus 中使用 apply 方法添加原生 SQL 条件

正确使用这些技术可以有效地查询和处理 VARCHAR 中存储的 JSON 数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/78837.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

路由器开启QOS和UPNP的作用

QOS 的作用 保障关键业务带宽&#xff1a;可根据网络应用的重要性分配带宽。比如在家庭网络中&#xff0c;当多人同时使用网络时&#xff0c;将视频会议等实时性要求高的关键业务设置为高优先级&#xff0c;确保其能获得足够带宽&#xff0c;避免卡顿&#xff0c;而文件下载等…

5G网络下客户端数据业务掉线频繁

MCPTT&#xff08;Mission Critical Push-to-Talk&#xff09;客户端的日志&#xff0c;和界面在待机状态下&#xff08;即没有做通话等业务操作&#xff09;&#xff0c;会频繁提示“离线”。 主要先看有没有丢网&#xff0c;UL BLER有没有问题。确认没有问题。看到业务信道释…

使用Python和Matplotlib可视化字体轮廓:从路径数据到矢量图形

引言 字体设计和矢量图形处理是编程中一个有趣且实用的领域。通过Python的matplotlib库&#xff0c;我们可以轻松将字体轮廓的路径数据转换为直观的矢量图形。本文将带你一步步实现这一过程&#xff0c;并解析代码细节&#xff0c;帮助你理解如何将复杂的路径指令转化为可视化…

4.13日总结

javafx中实现发送qq邮箱验证码: 手动导入jar包方法&#xff1a; 第一步&#xff1a;开启QQ邮箱的 POP3/IMAP 或者 SMTP/IMAP 服务 打开qq邮箱&#xff08;电脑端&#xff09;&#xff0c;找到设置里的账号与安全的安全设置&#xff0c;往下滑就可以找到 POP3/IMAP 或者 SMTP…

智慧乡村数字化农业全产业链服务平台建设方案PPT(99页)

1. 农业全产业链概念 农业全产业链是依托数字化、电子商务、云计算等技术&#xff0c;整合规划咨询、应用软件设计与开发等服务&#xff0c;推动农业产业升级和价值重塑&#xff0c;构建IT产业融合新生态。 2. 产业链技术支撑 利用云计算、大数据、区块链等技术&#xff0c;为…

k8s的配置文件总结

在 Kubernetes 中&#xff0c;配置文件 是定义集群资源的核心&#xff0c;通常以 YAML 或 JSON 格式编写。以下是 Kubernetes 中关键的配置文件类型及其作用&#xff1a; 1. 核心工作负载配置 (1) Deployment • 用途&#xff1a;定义无状态应用的 Pod 副本管理策略&#xff…

STM32(基于标准库)

参考博客&#xff1a;江科大STM32笔记 Stm32外设 一、GPIO 基础 GPIO位结构 I/O引脚的保护二极管是对输入电压进行限幅的上面的二极管接VDD, 3.3V,下面接VSS, 0V&#xff0c;当输入电压 >3.3V 那上方这个二极管就会导通&#xff0c;输入电压产生的电流就会大部分充入VD…

为什么我们需要if __name__ == __main__:

[目录] 0.前言 1.什么是 __name__&#xff1f; 2.if __name__ __main__: 的作用 3.为何Windows更需if __name__ &#xff1f;前言 if __name__ __main__: 是 Python 中一个非常重要的惯用法&#xff0c;尤其在使用 multiprocessing 模块或编写可导入的模块时。它的作用是区分…

速盾:高防CDN的原理和高防IP一样吗?

随着互联网的发展&#xff0c;网络安全威胁日益严重&#xff0c;尤其是DDoS攻击、CC攻击等恶意行为&#xff0c;给企业带来了巨大的风险。为了应对这些挑战&#xff0c;许多企业开始采用高防CDN&#xff08;内容分发网络&#xff09;和高防IP作为防御措施。尽管两者都能提供一定…

《算法笔记》3.6小节——入门模拟->字符串处理

1009 说反话 #include <cstdio>int main() {char sen[80][80];int num0;while(scanf("%s",sen[num])!EOF){num;}for (int i num-1; i > 0; --i) {printf("%s ",sen[i]);}printf("%s\n",sen[0]);return 0; }字符串连接 #include <io…

供应链业务-供应链全局观(三)- 供应链三流的集成

概述 供应链的全局观的全两篇文章主要描述了供应链的基础概念和供应链的协作和集成问题。 供应链业务-供应链全局观&#xff08;一&#xff09;定义了什么是供应链和供应链管理。 所谓供应链就是把采购进来的东西&#xff0c;通过自身的生成加工&#xff0c;进行增值服务&am…

链表-算法小结

链表 单链表 双链表 循环链表 链表_stl-CSDN博客 虚拟头结点 反转链表 删除链表元素 方法一: 直接使用原来的链表来进行删除操作。 头节点是否为空头链表的值是否为要删除的值头结点删除后,新的头节点是否依旧要删除 ,删除后的,新头节点可能是空结点 方法二: 设置一个虚拟…

C语言中常用的调试宏和函数总结(__LINE__、__FUNCTION__)

表格&#xff1a;C语言调试工具 类别工具描述示例代码预定义宏__LINE__表示当前源代码的行号。printf("Error occurred at line %d\n", __LINE__);__FILE__表示当前源代码文件的名称。printf("Error occurred in file %s\n", __FILE__);__func__表示当前函…

DotnetCore开源库SampleAdmin源码编译

1.报错: System.Net.Sockets.SocketException HResult0x80004005 Message由于目标计算机积极拒绝&#xff0c;无法连接。 SourceSystem.Net.Sockets StackTrace: 在 System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, C…

如何使用切片操作来处理序列数据

1 问题 本文主要探究 Python 中切片操作的原理和应用。具体来说&#xff0c;我们将分析切片的基本语法、切片的步长和切片的边界&#xff0c;并通过示例代码展示如何使用切片操作来处理序列数据。 2 方法 为了更好地理解切片操作&#xff0c;我们采用如下的思路学习python中的切…

java(二):java的运算和流程控制

java中单引号和双引号区别和用法 区别1&#xff1a;java中的单引号表示字符&#xff0c;双引号表示字符串。 区别2&#xff1a;单引号引的数据一般是char类型的&#xff1b;双引号引的数据 是String类型的。 区别3&#xff1a;java中单引号里面只能放一个字母或数字或符号&…

Android envsetup与Python venv使用指南

Android envsetup 和 Python venv 是两种完全不同的环境配置工具&#xff0c;分别服务于不同的开发场景。以下是对它们的详细解释及使用方法&#xff1a; 1. Android envsetup 用途&#xff1a; Android envsetup 是 Android 源码开发中的环境配置脚本&#xff08;envsetup.sh…

游戏引擎学习第222天

回顾昨天的过场动画工作 我们正在制作一个游戏&#xff0c;目标是通过直播的方式完成整个游戏的开发。在昨天的工作中&#xff0c;我享受了制作过场动画的过程&#xff0c;所以今天我决定继续制作多个层次的过场动画。 昨天我们已经开始了多层次过场动画的基本制作&#xff0…

Leedcode刷题 | Day31_贪心算法05

一、学习任务 56. 合并区间代码随想录738. 单调递增的数字968. 监控二叉树 二、具体题目 1.56合并区间56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 给出一个区间的集合&#xff0c;请合并所有重叠的区间。 示例 1: 输入: intervals [[1,3],[2,6],[8,10],[15,1…

app逆向专题五:新快报app数据采集

app逆向专题五:新快报app数据采集 一、抓包寻找数据接口二、编写代码三、完整代码一、抓包寻找数据接口 打开charles,并在手机端打开新快报app,点击“广州”或者“经济”等选项卡,抓包,寻找数据接口,如图所示: 二、编写代码 这里介绍一种简便的代码编写方法,在数据…