MySQL 5.7+ 的 JSON 字段需用 JSON 函数查询:JSON_CONTAINS() 查数组包含(值须加双引号),JSON_EXTRACT() 或 ->/->> 提取键值后比较(->> 自动去引号),数字可直接运算;PHP 中须防注入,路径白名单、值用参数绑定或 json_encode;高频查询应建虚拟列+索引。

MySQL 5.7+ 的 JSON 字段不能直接用 WHERE json_column = 'xxx' 比较,必须用 JSON 函数提取后再查。
用 JSON_CONTAINS() 查包含关系
适合查数组型 JSON 中是否含某个值,比如 {"tags": ["php", "mysql"]} 里有没有 "mysql":
-
JSON_CONTAINS(tags, '"mysql"')—— 注意字符串值要加双引号包裹("mysql"是 JSON 字符串,mysql不是) -
JSON_CONTAINS(tags, '"php"', '$.tags')—— 指定路径更安全,避免误匹配嵌套字段 - 不支持模糊匹配或正则,只认完整 JSON 值(
"PHP"≠"php")
用 JSON_EXTRACT() 或 -> 操作符取值后比较
适合查对象中某个键的精确值,比如 {"status": "active", "score": 95}:
-
JSON_EXTRACT(data, '$.status') = '"active"'—— 返回带引号的 JSON 字符串,所以右边也要加引号 -
data->'$.status' = '"active"'—— 简写语法,效果一样 -
data->>'$.status' = 'active'——->>是去引号版本,右边直接写纯字符串 - 对数字字段,
data->>'$.score' > 90可直接参与数值比较(MySQL 会隐式转换)
PHP 中拼接 JSON 查询要防注入
别把用户输入直接塞进 JSON 路径或值里,尤其用 -> 语法时:
立即学习“PHP免费学习笔记(深入)”;
- 路径部分(如
'$.key')必须白名单校验,不能由用户控制;否则可能注入'$."a"; DROP TABLE x; -- ' - 值部分要用 PDO 参数绑定:
$stmt = $pdo->prepare("SELECT * FROM t WHERE JSON_CONTAINS(meta, ?)"); $stmt->execute(['"' . $pdo->quote($tag) . '"']); - 用
json_encode($value, JSON_UNESCAPED_UNICODE)生成安全 JSON 字符串再传入,比手拼引号更可靠
JSON 字段查询性能容易被忽略:没建虚拟列 + 索引的话,每次都要全表解析 JSON;->> 表达式虽方便,但无法直接走索引——真要高频查某个键,得配 GENERATED COLUMN 加普通索引。










