当前位置: 首页 > news >正文

【MySQL】MySQL `JSON` 数据类型介绍

自 MySQL 5.7 引入原生 JSON 数据类型以来,它已成为处理半结构化数据的利器。本指南将全面覆盖 JSON 类型的写入、读取、更新、删除、高级查询及性能优化

1. 核心优势与适用场景

  • 三大优势:
    1. 自动格式验证: 保证存入的数据一定是有效的JSON。
    2. 优化二进制存储: 读取JSON内部元素时比文本解析更快。
    3. 丰富的内置函数: 提供强大的查询和操作能力。
  • 适用场景:
    • 商品规格、文章标签、用户配置等多变属性的存储。
    • 不适用场景: 用户ID、用户名等高度结构化、需要频繁精确查询的核心数据,仍应使用传统字段。

2.【写入】构造与插入 JSON 数据

这是JSON类型最基础的操作:如何创建并写入数据。

A. 插入预先格式化的JSON字符串(基本方式)

这是最常见的方式,在你的应用程序代码中(如Python, Java)将对象序列化为JSON字符串,然后直接插入。

CREATE TABLE IF NOT EXISTS products (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,properties JSON
);INSERT INTO products (name, properties) VALUES
('笔记本电脑', '{"brand": "Apple", "ram_gb": 16, "tags": ["MacBook Pro", "M2 Chip"]}'),
('智能手机', '{"brand": "Samsung", "ram_gb": 12, "screen_size": 6.8, "colors": ["Black", "White"]}');

B. 使用函数在SQL中动态构造JSON(进阶方式)

有时候,你需要直接在数据库层面根据其他表的数据来生成JSON。这时 JSON_OBJECTJSON_ARRAY 就派上用场了。

  • JSON_OBJECT('key1', val1, 'key2', val2, ...): 根据键值对创建JSON对象。
  • JSON_ARRAY(val1, val2, ...): 根据值创建JSON数组。

示例:动态插入一个键盘商品

INSERT INTO products (name, properties)
VALUES ('机械键盘',-- 使用函数动态生成JSON对象JSON_OBJECT('brand', 'Logitech','type', 'Mechanical','backlight', true,'switches', JSON_ARRAY('Red', 'Brown', 'Blue') -- 嵌套一个JSON数组)
);

这个方法在数据迁移或复杂的数据处理场景中非常有用。


3.【读取】查询与解析 JSON 数据

查询是JSON类型最强大的部分。

A. 基础路径提取:->->>

这是最重要的查询操作符,必须理解其区别:

  • column->path: 提取并返回JSON格式的值。字符串会带双引号。
  • column->>path: 提取并返回纯文本格式的值。字符串不带双引号,适合用于WHERE条件判断或给应用程序返回干净的数据。
SELECTname,properties->"$.brand" AS brand_with_quotes,  -- 结果: "Apple"properties->>"$.brand" AS brand_without_quotes, -- 结果: Appleproperties->"$.tags" AS tags_array           -- 结果: ["MacBook Pro", "M2 Chip"]
FROM products
WHERE id = 1;

B. 在 WHERE 子句中筛选

-- 查询品牌是 Apple 的商品
SELECT name, properties FROM products WHERE properties->>"$.brand" = 'Apple';-- 查询内存大于等于 16GB 的商品 (注意类型转换)
SELECT name, properties FROM products WHERE CAST(properties->>"$.ram_gb" AS UNSIGNED) >= 16;

C. 查询数组元素

  • 按索引查询: $[0] 代表数组第一个元素。
    SELECT properties->>"$.tags[0]" AS first_tag FROM products WHERE id = 1; -- 结果: MacBook Pro
    
  • 判断值是否存在于数组中: JSON_CONTAINS()
    -- 查询所有包含 "White" 颜色的手机
    -- 第二个参数 '"White"' 是一个JSON字符串,所以引号是必须的
    SELECT name FROM products WHERE JSON_CONTAINS(properties->'$.colors', '"White"');
    

D. (高级) 将JSON数组展开为行:JSON_TABLE()

MySQL 8.0 开始,JSON_TABLE() 是一个划时代的函数,它可以将JSON数组展开成规范的关系型数据行,便于进行聚合、关联等操作。

示例:列出所有商品的所有标签

SELECTp.name,t.tag
FROMproducts p,-- 将 properties 字段中的 tags 数组展开JSON_TABLE(p.properties,'$.tags[*]' -- [*] 表示数组中的所有元素COLUMNS (tag VARCHAR(50) PATH '$' -- 将每个数组元素的值映射到名为 tag 的列)) AS t;

结果:

nametag
笔记本电脑MacBook Pro
笔记本电脑M2 Chip

4.【修改/删除】更新 JSON 数据

A. 更新或新增键值对:JSON_SET, JSON_REPLACE, JSON_INSERT

  • JSON_SET(): 最常用。路径存在则更新,不存在则新增。
  • JSON_REPLACE(): 只更新存在的路径。
  • JSON_INSERT(): 只新增不存在的路径。
-- 为Apple笔记本电脑更新内存为32GB,并增加发布年份
UPDATE products
SET properties = JSON_SET(properties,'$.ram_gb', 32,'$.year', 2025
)
WHERE properties->>"$.brand" = 'Apple';

B. 删除键值对:JSON_REMOVE()

-- 删除商品属性中的 'screen_size'
UPDATE products
SET properties = JSON_REMOVE(properties, '$.screen_size')
WHERE name = '智能手机';

5. 性能优化与最佳实践

A. 为JSON字段创建索引

不能直接索引整个JSON列,但可以为JSON内部频繁查询的特定路径创建索引。方法是使用生成列 (Generated Column)

示例:为 brand 字段创建索引

-- 1. 添加一个虚拟列,其值总是从 properties->>"$.brand" 计算得来
ALTER TABLE products
ADD COLUMN brand_name VARCHAR(255) AS (properties->>"$.brand") VIRTUAL;-- 2. 在这个虚拟列上创建索引
CREATE INDEX idx_products_brand_name ON products(brand_name);

之后,所有 WHERE brand_name = '...' 的查询都会自动使用该索引,速度飞快!

B. 添加检查约束(CHECK

为了保证JSON内部数据的某种一致性,你可以添加 CHECK 约束。

-- 确保所有商品的properties字段都必须包含 brand 和 ram_gb 这两个键
ALTER TABLE products
ADD CONSTRAINT chk_properties_keys
CHECK (JSON_CONTAINS_PATH(properties, 'all', '$.brand', '$.ram_gb')
);

6. 总结

  • 写入: 可以直接插入字符串,也可以用 JSON_OBJECTJSON_ARRAY 在SQL中动态构造。
  • 读取: ->->> 是基础,JSON_CONTAINS 用于数组查询,JSON_TABLE (MySQL 8.0+) 是处理数组的强大工具。
  • 修改: JSON_SET 是最常用的更新函数。
  • 性能: 必须为你频繁查询的JSON路径,通过生成列的方式来创建索引。

JSON 数据类型是关系型数据库对现代应用需求的一种强大补充,但它应该被用来补充而不是替代良好的关系型设计。

http://www.dtcms.com/a/486343.html

相关文章:

  • 通过hutool生成xml
  • vue.config.js 文件功能介绍,使用说明,对应完整示例演示
  • 无极分期网站临沂做网络优化的公司
  • Vue3的路由Router【7】
  • DOM 实例
  • 网站安全建设需求分析报告重庆有哪些科技骗子公司
  • Springboot AOP Aspect 拦截中 获取HttpServletResponse response
  • 【深度学习理论基础】什么是蒙特卡洛算法?有什么作用?
  • 网站建设商虎小程序就业网站建设
  • 从留言板开始做网站企业网站建设代理加盟
  • USB——UVC简介
  • cocosCreator导出Web-Mobile工程资源加载时间分析
  • SpringCloud系列(53)--SpringCloud Sleuth之zipkin的搭建与使用
  • 虚拟主机做视频网站可以吗网络规划的主要步骤
  • 【sqlite】xxx.db-journal是什么?
  • Ubuntu 搭建 Samba 文件共享服务器完全指南
  • ubuntu server版本安装vmtool
  • 《Redis库基础使用》
  • 网站转应用济南网站优化推广公司电话
  • 探索libsignal:为Signal提供强大加密保障的开源库
  • PIL与OpenCV双线性插值实现差异导致模型精度不够踩坑
  • 逆合成孔径雷达成像的MATLAB算法实现
  • 网站定制建设公司启信宝企业查询官网
  • html案例:制作一个图片水印生成器,防止复印件被滥用
  • 最新版谷歌浏览器集成知笺云阅读器控件介绍
  • 嘉定装饰装修网站企业网络营销青岛
  • break,continue练习题
  • 【Ubuntu 24.04.3 LTS(Noble Numbat)】移动硬盘数据提取操作手册
  • 网站开发需求分析与功能设计互联网线上推广是什么工作
  • 做网站前应该怎么处理微信推广文案范文