mysql 8.0因rank等新增保留关键字导致union查询报error 1064,需用反引号或重命名规避;json、group等同理;同时注意only_full_group_by启用及information_schema表名变更影响。

Union查询失败直接报ERROR 1064?先查是不是撞了RANK
MySQL 8.0 把 RANK 加进了保留关键字列表,而 5.7 没有。如果你的 UNION 查询里用了 RANK 当列别名、表别名或字段名(比如 SELECT id AS rank FROM t1 UNION SELECT id AS rank FROM t2),升级后会直接报 ERROR 1064 (42000): You have an error in your SQL syntax,错误位置往往卡在 AS rank 这里。
这不是语法写错,是解析器在词法分析阶段就拒绝了——RANK 已被硬编码为关键字,不能当标识符用,除非加反引号。
- 快速确认方式:
SELECT keyword FROM INFORMATION_SCHEMA.KEYWORDS WHERE RESERVE = 1 AND keyword = 'RANK';(8.0 返回一行,5.7 空) - 临时绕过:把所有
rank改成`rank`,但不推荐长期用,易读性差且可能干扰 ORM 映射 - 真正该做的:批量搜索代码和视图定义中所有
AS rank、JOIN ... rank、ORDER BY rank等上下文,统一重命名为rank_no或ranking_val等非保留词
为什么UNION ALL也报错?检查JSON和GROUP是否混入别名
JSON 和 GROUP 同样是 8.0 新增保留字,但它们比 RANK 更隐蔽:只在特定上下文中触发冲突。例如 SELECT data AS json FROM t1 UNION SELECT data AS json FROM t2 在 5.7 能跑,在 8.0 会报错;同理 SELECT name AS group FROM t 在 UNION 中也会崩。
这类问题常出现在动态拼 SQL 的业务逻辑里(比如报表导出模块),人眼很难扫全。
- 查视图:
SELECT TABLE_NAME, VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE VIEW_DEFINITION LIKE '%AS json%' OR VIEW_DEFINITION LIKE '%AS group%'; - 查存储过程/函数:
SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_DEFINITION REGEXP 'AS[[:space:]]+(json|group|rank)[[:space:]]*(,|FROM|UNION|ORDER)'; - 注意大小写:MySQL 关键字默认不区分大小写,
AS JSON、as json、As Json全部命中
升级前没报错,升级后UNION突然失效?重点看sql_mode变化
8.0 默认启用了 ONLY_FULL_GROUP_BY,而很多 UNION 查询会隐式触发 GROUP BY 行为(比如含聚合函数 + 非聚合字段)。即使你没写 GROUP BY,优化器也可能重写执行计划,导致字段合法性校验失败。
典型现象:单独执行两个子查询都正常,UNION 一组合就报 ERROR 1055,提示某列“not in GROUP BY clause”。
- 不要直接关
ONLY_FULL_GROUP_BY,先用EXPLAIN FORMAT=TREE看执行计划里有没有隐式分组 - 检查
UNION各分支的 SELECT 列表是否完全一致(类型、长度、别名),尤其注意函数调用结果是否被当成“非确定性列” - 若必须兼容旧逻辑,可在会话级临时调整:
SET SESSION sql_mode = REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', '');,但上线前务必回归测试
别只盯着UNION本身——INFORMATION_SCHEMA表名冲突也会连带报错
8.0 新增了一批以 INNODB_ 开头的系统表(如 INNODB_TABLES、INNODB_COLUMNS)。如果你的业务代码里写了类似 SELECT * FROM t1 UNION SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES,升级后可能报错,不是语法问题,而是权限或表不存在(老版本没这些表)。
更麻烦的是,有些 ORM 或监控脚本会自动探测库结构,悄悄访问这些新表,进而让 UNION 查询因上游依赖失败而中断。
- 查可疑引用:
SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_DEFINITION LIKE '%INFORMATION_SCHEMA.INNODB_%'; - 禁用非必要系统表访问:在应用连接串里加
session_track_system_variables=OFF,减少自动探查 - 生产环境禁止直接查
INFORMATION_SCHEMA做业务逻辑,这类查询在 8.0 性能更差,且语义不稳定
真正容易被忽略的点是:关键字冲突不只发生在 SELECT 列表,还藏在 ORDER BY、HAVING、子查询的 WITH 子句里。升级前用 util.checkForServerUpgrade() 扫一遍,比手动 grep 可靠得多——它能识别上下文敏感的保留字使用场景。











