添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

MySQL 中提取 JSON 字段数据的方法

由于保存用户上传数据时,有一部分的字段为固定的,但不同用户对应的具体数据部分字段不固定,因此使用 MySQL 的 json 类型保存不固定的部分,将不固定的这部分字段统一放入 value 字段下,value 类型设为 json。
但在使用 MySQL 的 MAX 函数统计 value 下的字段时,发现统计结果异常,因此发现在 MySQL 中不同提取 JSON 字段数据的方法结果的不同。

提取 JSON 字段数据的常用方法

使用 -> ->> 操作符:

  • -> 操作符用于提取 JSON 字段中的 JSON 值,可以通过键路径访问嵌套的属性: json_column->'$.key'
  • ->> 操作符用于提取 JSON 字段中的字符串值,类似于 -> ,但返回的是文本而不是 JSON: json_column->>'$.key'
  • 使用 JSON_VALUE() JSON_EXTRACT() 函数:

  • JSON_VALUE() 函数用于提取 JSON 字段中指定键的值作为字符串。可以通过键路径访问嵌套的属性: JSON_VALUE(json_column, '$.key')
  • JSON_EXTRACT() 函数用于提取 JSON 字段中指定键的值作为 JSON。可以使用 $ 符号指定键路径: JSON_EXTRACT(json_column, '$.key')
  • CREATE TABLE `json_test`  (
      `id` int(0) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
      `value` json NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
    
    INSERT INTO `json_test` VALUES (1, 'server_1', '{\"ip\": \"192.168.1.10\", \"ssh\": {\"port\": 22, \"password\": \"1234\", \"username\": \"test\"}, \"total_disk\": 100}');
    INSERT INTO `json_test` VALUES (2, 'server_2', '{\"ip\": \"192.168.1.11\", \"ssh\": {\"port\": 22, \"password\": \"1234\", \"username\": \"test\"}, \"total_disk\": 100}');
    INSERT INTO `json_test` VALUES (3, 'server_3', '{\"ip\": \"192.168.1.12\", \"ssh\": {\"port\": 22, \"password\": \"1234\", \"username\": \"test\"}, \"total_disk\": 100}');
    

    ->JSON_EXTRACT取出的结果类似,都是 json 数据,如果值是字符串会带上""

    SELECT value->'$.ip' FROM json_test

    "192.168.1.10"
    "192.168.1.11"
    "192.168.1.12"
    

    SELECT JSON_EXTRACT(value, '$.total_disk') FROM json_test

    也可以使用JSON_UNQUOTE去掉""SELECT JSON_UNQUOTE(JSON_EXTRACT(value, '$.ssh.username')) FROM json_test

    当使用->>JSON_VALUE时,由于返回的是字符串,在使用 MySQL 的函数时,可能会出现问题,比如:SELECT MAX(JSON_VALUE(value, '$.total_disk')) FROM json_test,返回结果为 500,使用SELECT MAX(JSON_EXTRACT(value, '$.total_disk')) FROM json_test时,返回正确结果 1000

    性能考虑和最佳实践

  • 考虑性能方面的问题,尽量避免在查询中频繁使用 JSON 字段的提取操作。
  • 当需要大量处理 JSON 数据时,考虑使用 MySQL 8.0+ 版本提供的 JSON_TABLE() 函数,将 JSON 数据解析为关系型数据。
  • 注意事项和限制

  • 确保 JSON 字段的格式和路径的正确性,避免语法错误导致的查询问题。
  • 注意不同 MySQL 版本对于 JSON 函数和操作符的支持程度,避免使用不受支持的功能。
  •