我们口头说的 JSON:是文本格式(字符串文本,遵循 JSON 规范);MySQL 里的 JSON:是 MySQL 的原生字段类型,是结构化二进制类型,不是普通字符串。
1. 普通 JSON(通用 JSON 文本)
本质:utf8 字符串,肉眼可读 示例文本:
["2091442067807932672",123]
特点:
- 只是一段文本,数据库当成普通
varchar/text - 数据库不知道里面是数组、数字、字符串;你要自己解析
- 比较:直接字符串比对,
"123"和123不一样 - 缺点:不能用
JSON_CONTAINS、->、JSON_EXTRACT原生函数高效检索、索引 - 风险:超长数字直接写会丢失精度(JSON number 本身的坑)
2. MySQL JSON 字段类型(mysql 5.7+)
本质:MySQL 内部二进制结构化存储类型
存入时:MySQL 自动把 JSON 文本解析、校验、转成内部二进制结构,不是原样存字符串 取出时:再序列化成 JSON 文本给你看
特点:
内置识别 JSON 的 6 种值类型:object / array / number / string / boolean / null 支持原生函数:JSON_CONTAINS / JSON_SEARCH / -> / ->>
强类型匹配
-- 数组:[2091442067807932672] 元素是 JSON number
JSON_CONTAINS(col, CAST('2091442067807932672' AS JSON)) 能匹配
JSON_CONTAINS(col, CAST('"2091442067807932672"' AS JSON)) 不能匹配
-- 数组:["2091442067807932672"] 元素是 JSON string
JSON_CONTAINS(col, CAST('"2091442067807932672"' AS JSON)) 能匹配
JSON_CONTAINS(col, CAST('2091442067807932672' AS JSON)) 不能匹配
限制:
- 写入非法 JSON 会直接报错(varchar 存 json 文本不会报错)
- 超大雪花 ID 作为 JSON number 依然丢失精度(底层 double 存储)
- MySQL JSON 原生不支持直接建普通 B 树索引,需要生成虚拟列建索引
3. 对比速查表
表格
| 项目 | 通用 JSON 文本(varchar 存) | MySQL JSON 字段类型 |
|---|---|---|
| 存储形式 | 原始字符串文本 | 解析后的二进制结构 |
| 合法性校验 | 不校验,脏 JSON 也能存 | 写入强制校验 JSON 格式,非法直接报错 |
| 类型感知 | 无,只是一串文字 | 识别 number/string/array/object,强类型 |
| 查询函数 | 只能 like、正则,很慢 | JSON 系列内置函数,按 JSON 语义匹配 |
| 精度坑 | 自己控制,加引号就是字符串 | JSON number 用 double,超长 ID 丢精度 |
| 适用场景 | 只存、几乎不检索里面元素 | 需要频繁查询数组内元素、解析 key-value |
4. 结合 业务的最佳方案(金蝶单据 ID 这种超长数字)
MySQL JSON 数组存 JSON string:
["2091442067807932672","2091442067807932673"]
查询写法:
-- 目标值包双引号,转成JSON string类型匹配
JSON_CONTAINS(your_json_col, CAST('"2091442067807932672"' AS JSON))