MySQL 8.0 中 rank、json、group 等词为保留关键字,需用反引号包裹字段/表名/别名,否则报错;可用 mysqlsh 的 util.checkForServerUpgrade() 或 INFORMATION_SCHEMA 查询快速识别,并优先采用反引号而非改名。

rank、json、group 这类词在 MySQL 8.0 中已成保留关键字,5.7 能跑的 SQL 在 8.0 直接报 ERROR 1064 (42000)——不是语法写错,是解析器直接拒识。
怎么快速识别哪些字段/表名撞了保留字
别靠猜。用官方检查工具直接扫:
-
mysqlsh -uroot -p -S /tmp/mysql.sock -e "util.checkForServerUpgrade()"报告里会明确标出Column name 'rank' is a reserved keyword这类 ERROR 级条目 - 手动查:执行
SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME IN ('rank', 'json', 'group', 'window', 'role');(把常见新增关键字列进去) - 导出 SQL 后 grep 也行:
grep -n -E '\b(rank|json|group|window)\b' dump.sql,注意加单词边界避免误匹配
修复方式:反引号不是可选项,是必选项
只要字段名、表名、别名用了保留字,就必须用反引号包裹,否则 8.0 解析失败。这不是风格问题,是语法硬性要求。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 错的写法:
SELECT id, rank FROM user_score ORDER BY rank; - 对的写法:
SELECT id, `rank` FROM user_score ORDER BY `rank`; - 视图或存储过程里同样适用——哪怕只是
AS rank别名也要改成AS `rank` - Navicat 或其他 GUI 工具生成的建表语句若含
rank INT,导出后得手动补成`rank` INT
为什么不能全局改名?
看起来一劳永逸,但实际风险高、成本大:
- 应用代码里硬编码了字段名(如 ORM 的 Model 定义、MyBatis 的 resultMap),改 DB 字段名 ≠ 改所有调用点
- 历史 SQL 日志、慢查询日志、监控埋点都依赖原名,改名后无法对齐
- 有些字段名是业务术语(比如游戏排行榜的
rank),语义清晰,强行改成user_rank反而模糊 - MySQL 8.0 允许反引号兜底,这是设计好的兼容路径,没必要绕远路
容易被忽略的坑:ORDER BY 和 GROUP BY 里的别名
5.7 允许 SELECT a+1 AS rank FROM t ORDER BY rank,8.0 会报错——因为 ORDER BY 后的 rank 被当成关键字而非别名解析。
- 必须写成:
SELECT a+1 AS `rank` FROM t ORDER BY `rank`; - 更稳妥的做法是避免用保留字作别名,哪怕加了反引号,某些旧版 JDBC 驱动(如 mysql-connector-java < 8.0.13)仍可能解析异常
- GROUP BY 同理:
GROUP BY `rank`才安全,光靠上下文推断不可靠
util.checkForServerUpgrade() 扫一遍,它比人眼靠谱得多。

















