必须用 stored 而非 virtual 创建 json 提取生成列,因 mysql 8.0+ 禁止在 virtual 列中使用 json 函数;提取时优先用 ->> 获取去引号字符串,并显式声明数据类型以支持索引和正确比较。

虚拟生成列必须用 STORED,不能用 VIRTUAL
MySQL 的 JSON 字段本身不支持直接用于 VIRTUAL 生成列的表达式——哪怕只是 JSON_EXTRACT 或 -> 操作,也会报错 ERROR 3105 (HY000): The value specified for generated column is not allowed。根本原因是 MySQL 在 8.0 中限制了 VIRTUAL 列对 JSON 函数的使用(包括 JSON_EXTRACT、JSON_UNQUOTE、->、->> 等),但 STORED 列允许。
所以第一步必须明确:要从 JSON 字段提取值建生成列,只能选 STORED。
-
GENERATED ALWAYS AS (...) STORED✅ 可用 -
GENERATED ALWAYS AS (...) VIRTUAL❌ 报错,即使表达式语法完全正确 - 部分文档或旧版本示例写 VIRTUAL,实际在 8.0.22+ 会失败,别信
提取 JSON 值时优先用 ->> 而不是 -> 或 JSON_EXTRACT
->> 是 JSON_UNQUOTE(JSON_EXTRACT(...)) 的语法糖,它返回去引号后的字符串(如 "admin" → admin),而 -> 和 JSON_EXTRACT 返回带双引号的 JSON 字符串(如 "admin")。这对生成列的类型推导和后续查询影响很大。
比如你想提取 user_info 字段里的 role 并建为 VARCHAR(20) 类型的生成列:
ALTER TABLE users ADD COLUMN role VARCHAR(20) GENERATED ALWAYS AS (user_info->>'$.role') STORED;
- 用
->>→ 生成列值是干净字符串,可直接用于=、IN、索引等 - 用
->→ 值是"admin"(含引号),类型被推为json,无法建普通 B-tree 索引,且WHERE role = 'admin'永远不匹配 -
JSON_EXTRACT(user_info, '$.role')同样返回带引号字符串,效果等同于->
生成列加索引前必须显式指定数据类型
MySQL 不会自动为 JSON 提取表达式推导出合适的非 JSON 类型。如果你只写 GENERATED ALWAYS AS (user_info->>'$.role') STORED,MySQL 默认推导为 LONGTEXT,这会导致索引效率差、排序慢,还可能触发隐式转换问题。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
务必显式声明目标类型:
ALTER TABLE users
ADD COLUMN status ENUM('active','inactive','pending')
GENERATED ALWAYS AS (user_info->>'$.status') STORED,
- 用
ENUM、VARCHAR(N)、INT、TINYINT等具体类型,别依赖默认 - 如果 JSON 中字段可能为
null,确保类型允许 NULL(如没加NOT NULL);否则插入 null 值会报错 - 对数字字段,用
CAST(user_info->>'$.score' AS SIGNED)显式转整型,避免字符串比较
WHERE 条件里不要在生成列上再套 JSON 函数
一旦你建好了 role 这个 STORED 生成列,它的值已经是普通字符串了。这时候再写 WHERE role->>'$[0]' 或 WHERE JSON_CONTAINS(role, ...) 就完全错误——role 不是 JSON 类型,而是 VARCHAR,套 JSON 函数会报错或返回 NULL。
正确做法是把逻辑前置到生成列定义里:
- 想查 JSON 数组第一个角色?定义生成列为
user_info->>'$[0]',而不是role再处理 - 想判断某个键是否存在?用
JSON_CONTAINS_PATH(user_info, 'one', '$.tags')作为生成列表达式,类型设为TINYINT - 生成列建好后,就当它是普通字段用:
WHERE role = 'admin'、ORDER BY role
最容易被忽略的一点:生成列的值在 INSERT/UPDATE 时计算并固化,之后不再随原始 JSON 变动而更新——除非你改的是原始 JSON 字段本身。这点和视图不同,得心里有数。










