开发者

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

开发者 https://www.devze.com 2025-04-15 09:02 出处:网络 作者: yzhSWJ
目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2 查询多个 ID3.3 使用 JSON_OVERLAPS (MySQL 8.0+)3.4 查询特定权限的记录四、避免常见错误4.1 空值处理4.2 JSON 格式匹配4.3 确
目录
  • 一、问题背景
  • 二、mysql jsON 函数
    • 2.1 常用 JSON 函数
  • 三、查询示例
    • 3.1 基本查询
    • 3.2 查询多个 ID
    • 3.3 使用 JSON_OVERLAPS (MySQL 8.0+)
    • 3.4 查询特定权限的记录
  • 四、避免常见错误
    • 4.1 空值处理
    • 4.2 JSON 格式匹配
    • 4.3 确保 JSON 有效性
  • 五、在 MyBATis Plus 中的应用
    • 5.1 基本查询
    • 5.2 多条件查询
    • 5.3 查询多个 ID
  • 六、性能优化建议
    • 七、总结

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

      一、问题背景

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

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

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

      二、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 NULL
        AND app_ids != ''
        AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

      3.2 查询多个 ID

      SELECT * FROM sys_user
      WHERE 
        app_idsandroid IS NOT NULL
        AND 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 NULL
        AND 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 NULL
        AND 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 NULL
        AND app_ids != ''
        AND JSON_VALID(app_ids) = 1
        AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '19055554669javascript80773889'));

      五、在 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);

      六、性能优化建议

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

      添加索引:虽然无法直接为 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);

      定期维护:对于大表,定期 OPTIMIZE TABLE 有助于维护性能。

      七、总结

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

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

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

      到此这篇关于MySQL 中查询 VARCHAR 类型 JSON 数据的的文章就介绍到这了,更多相关mysql 查询 VARCHAR 类型 JSON 数据内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      关注公众号