MySQL 8.0.13+ 支持列默认值为表达式,且必须用括号包裹,否则报错ERROR 1064;仅TIMESTAMP/DATETIME的CURRENT_TIMESTAMP可省略括号,其他表达式如UUID_TO_BIN(UUID())、CURRENT_DATE + INTERVAL 1 YEAR等均需加括号。

MySQL 8.0.13+ 才支持列默认值为表达式,且必须用括号包裹,否则语法报错。
表达式默认值的语法必须加括号
MySQL 把常量默认值(如 DEFAULT 0、DEFAULT 'abc')和表达式默认值严格区分开:后者强制要求用圆括号包裹。漏括号会直接报错 ERROR 1064。
-
DEFAULT (UUID_TO_BIN(UUID()))✅ 正确 -
DEFAULT UUID_TO_BIN(UUID())❌ 报错:syntax error near UUID_TO_BIN -
DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR)✅ 正确 -
DEFAULT CURRENT_DATE + INTERVAL 1 YEAR❌ 解析失败
TIMESTAMP/DATETIME 是唯一例外,CURRENT_TIMESTAMP 不加括号
只有 TIMESTAMP 和 DATETIME 类型允许对 CURRENT_TIMESTAMP 省略括号——这是硬编码的特例,其他函数哪怕语义等价也不行。
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP✅ 允许(且推荐) -
created_at DATETIME DEFAULT (CURRENT_TIMESTAMP)❌ MySQL 会拒绝:Invalid default value for 'created_at' -
score FLOAT DEFAULT CURRENT_TIMESTAMP❌ 类型不匹配,直接报错
哪些表达式可用?注意版本与类型限制
能用作默认值的表达式必须满足:无参数、无副作用、可静态求值。常见合法组合:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
-
JSON_OBJECT('theme', 'dark')→ 用于JSON列 -
UUID_TO_BIN(UUID())→ 用于BINARY(16)存储二进制 UUID -
Point(0, 0)→ 用于POINT几何类型 -
RAND() * 100→ 用于数值列(但每次 INSERT 值都不同,慎用)
以下写法一律不被接受:
-
NOW()或SYSDATE()(仅CURRENT_TIMESTAMP特许) -
(SELECT ...)子查询 -
CONCAT('a', 'b')(MySQL 认为含函数调用,非纯常量表达式) -
1 + 1(看似简单,但 MySQL 8.0.13–8.0.28 中仍报错;8.0.29+ 才逐步放开部分字面量运算)
ALTER TABLE 添加表达式默认值要重写整列定义
对已有表加表达式默认值,ALTER TABLE ... ALTER COLUMN ... SET DEFAULT 语法**不支持表达式**——它只接受字面量。必须用 MODIFY COLUMN 并完整重申字段定义。
- 安全写法:
ALTER TABLE users MODIFY COLUMN id BINARY(16) DEFAULT (UUID_TO_BIN(UUID())) - 风险点:漏写
NOT NULL或其他约束,会导致原约束丢失 - 不能只写
ALTER TABLE users ALTER COLUMN id SET DEFAULT (UUID_TO_BIN(UUID()))—— 会报错ERROR 1064
真正容易被忽略的是:表达式默认值在 INSERT 时求值一次,不是建表时预计算;若表达式含随机或时间函数,每行结果都不同——这和常量默认值的行为本质不同。










