问题:解释一下下面这句sql并着重介绍一下JSON_UNQUOTE、JSON_EXTRACT。
mysql
SELECT
COUNT( 1 ) AS `cnt`
FROM
`t_production_line_model` `model`
WHERE
JSON_UNQUOTE(
JSON_EXTRACT( `model`.`toolLib`, '$.rackId' )) = 6
-- PARAMETERS: ["6"]
这条 SQL 的含义是:
查询表
t_production_line_model
中字段toolLib
的 JSON 数据中,键为rackId
的值为"6"
(字符串)或6
(数字)的记录数量。
🧠 SQL 语句详解:
mysql
SELECT COUNT(1) AS `cnt`
FROM `t_production_line_model` `model`
WHERE JSON_UNQUOTE(JSON_EXTRACT(`model`.`toolLib`, '$.rackId')) = 6
部分 | 解释 |
---|---|
COUNT(1) AS cnt |
统计满足条件的记录数量,起别名为 cnt |
FROM t_production_line_model model |
查询的表是 t_production_line_model ,别名为 model |
JSON_EXTRACT(toolLib, '$.rackId') |
从 toolLib 字段这个 JSON 字符串中提取键 "rackId" 对应的值 |
JSON_UNQUOTE(...) |
将提取的 JSON 值去除引号,使之变成普通 SQL 比较值 |
= 6 |
判断 JSON 中 "rackId" 的值是否等于数字 6 |
参数值:["6"] |
表示执行时传入的参数为字符串 "6" ,在对比时可能涉及类型转换 |
🔍 重点解析两个函数
✅ JSON_EXTRACT(json_doc, path)
作用 :从 JSON 字段中提取指定路径的值 语法:
mysql
JSON_EXTRACT(json_doc, '$.key')
JSON_EXTRACT(json_doc, '$[index]')
示例:
mysql
-- JSON 示例: {"rackId": 6, "toolIds": [1,2,3]}
JSON_EXTRACT('{"rackId":6}', '$.rackId') -- 返回 6(JSON 类型,带类型信息)
JSON_EXTRACT('{"toolIds":[1,2,3]}', '$.toolIds[1]') -- 返回 2
- 返回值是 JSON 类型(比如
"6"
、true
、null
,带双引号的是字符串) - 如果路径找不到,返回
NULL
✅ JSON_UNQUOTE(json_val)
作用 :将 JSON 格式的字符串值(如 "6"
)去掉引号变成普通值(如 6
),便于和 SQL 值做比较 语法:
mysql
JSON_UNQUOTE(JSON_EXTRACT(...))
示例:
mysql
JSON_UNQUOTE('"hello"') → hello
JSON_UNQUOTE('6') → 6
🧪 参数比较说明
你 SQL 中的比较是:
mysql
JSON_UNQUOTE(JSON_EXTRACT(toolLib, '$.rackId')) = 6
但传入的是参数:
mysql
["6"]
也就是:
mysql
... = "6"
- 如果
rackId
是字符串"6"
,这句能匹配; - 如果
rackId
是数字6
,MySQL 也能进行隐式类型转换匹配; - 不过推荐使用参数占位符:
mysql
... = ?
避免类型不一致的问题(建议和数据保持类型一致,"6"
vs 6
)。
✅ 总结
函数 | 作用 | 返回值类型 | 用途 |
---|---|---|---|
JSON_EXTRACT(json, path) |
提取 JSON 字段中的值 | JSON 类型(可能带引号) | 定位 JSON 中的数据 |
JSON_UNQUOTE(json_val) |
去除 JSON 中的字符串引号 | 普通字符串或数值 | 用于 SQL 比较 |
💡 最佳实践建议:
如果你确定 rackId
是数字类型,写法应更明确:
mysql
WHERE CAST(JSON_UNQUOTE(JSON_EXTRACT(toolLib, '$.rackId')) AS UNSIGNED) = ?
或者确保传入参数的类型与 JSON 中一致,避免隐式类型转换带来的问题。
如需,我也可以根据你实际 toolLib
的 JSON 结构,帮你设计更安全高效的查询方式。