MySQL 8.0 不支持 DATETIME DEFAULT CURRENT_TIMESTAMP,需改用 TIMESTAMP 或显式默认值;SHOW CREATE TABLE 输出差异、JSON_VALUE() 索引语法变更、字符集排序规则不一致导致 FIND_IN_SET 报错,迁移时须人工清理注释、统一 collation 并更新索引语法。

CREATE TABLE 中 DATETIME DEFAULT CURRENT_TIMESTAMP 报错
MySQL 8.0 严格区分 TIMESTAMP 和 DATETIME 的默认值能力。5.7 允许对 DATETIME 字段写 DEFAULT CURRENT_TIMESTAMP,但这是非标准行为;8.0 直接拒绝该语法,报错 Invalid default value for 'ts'。
- 必须改用
TIMESTAMP类型(支持该默认值) - 或改用显式默认值如
DEFAULT '1970-01-01 00:00:00' - 或在应用层、触发器中填充时间,而非依赖列定义
SHOW CREATE TABLE 输出差异引发迁移失败
5.7 导出的建表语句可能含 NO_FIELD_OPTIONS 等旧 sql_mode 控制项,而 8.0 已移除这些模式。当用 mysqldump 导出再导入时,若语句中带 /<em>!50100 ... </em>/ 注释或隐式依赖旧输出格式,8.0 解析会失败。
- 导出时不加
--compatible=5.7(它不解决根本问题) - 更稳妥的是:先在 5.7 执行
SHOW CREATE TABLE t\G,人工清理掉注释和冗余选项 - 或升级前用
mysqlpump(8.0 推荐替代 mysqldump)并指定--skip-definer和--skip-dump-rows验证结构
JSON_VALUE() 索引语法不兼容旧虚拟列写法
5.7 常用 AS (json_extract(...)) STORED + 普通索引模拟 JSON 子键查询;8.0 支持直接在 JSON_VALUE() 表达式上建函数索引,但语法更严。
- 5.7 写法:
ADD COLUMN j_name VARCHAR(100) AS (json_unquote(json_extract(data, '$.name'))) STORED - 8.0 正确写法:
CREATE INDEX idx_name ON t (JSON_VALUE(data, '$.name' RETURNING CHAR(100))) - 注意:8.0 不再允许对虚拟列使用
json_extract函数建索引,必须用JSON_VALUE - 若保留旧虚拟列,需确保其表达式返回类型与索引字段类型严格匹配(如
RETURNING CHAR(N))
字符集与排序规则混合导致 FIND_IN_SET 报错
8.0 默认库/表级 COLLATE 是 utf8mb4_0900_ai_ci,而 5.7 多为 utf8mb4_general_ci。升级后若表结构未统一 collation,FIND_IN_SET、CONCAT 等函数在跨字段比较时会触发 Illegal mix of collations。
- 查看当前列 collation:
SHOW FULL COLUMNS FROM t - 统一修改:
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci - 临时绕过(不推荐):
FIND_IN_SET(CAST(A_CODE AS CHAR CHARACTER SET utf8mb4), @xxx)
最易被忽略的是:DDL 兼容性问题往往藏在“导出→重建”流程的中间环节——比如 ORM 自动生成的 migration 脚本仍硬编码 5.7 语法,或 DBA 用 Navicat “生成建表语句”功能时未切换目标版本,结果导出的 SQL 在 8.0 里根本跑不通。


















