bigywater.tech
MySQL / InnoDB · 83

默认值表达式

给三列分别设置UUID()、NOW()、RAND()作为表达式默认值,真实插入三行空值,验证它们是不是每次都重新计算。

每行真实重新求值
UUID()和RAND()三行结果真实各不相同
需要一对括号
DEFAULT (expr)是MySQL识别表达式默认值的真实标志

做的事:三个非常量的DEFAULT表达式,真实插三次空值

代码CREATE TABLE default_expr ( id INT PRIMARY KEY AUTO_INCREMENT, uid VARCHAR(36) DEFAULT (UUID()), created_at DATETIME DEFAULT (NOW()), rand_val DOUBLE DEFAULT (RAND()) ); INSERT INTO default_expr () VALUES (), (), (); -- 真实什么值都不给

验证:三行真实各自算出了不一样的值

实测 · 本机执行输出
id  uid                                   created_at            rand_val
1   7ccbd492-bb29-11f1-8186-f496139cd556   2026-09-28 18:43:48   0.7270701497113985
2   7ccbd79e-bb29-11f1-8186-f496139cd556   2026-09-28 18:43:48   0.6057668240794603
3   7ccbd8d4-bb29-11f1-8186-f496139cd556   2026-09-28 18:43:48   0.8476237019967509

三行真实拿到了三个完全不同的UUID和随机数——每一行插入时都真实重新计算了一次UUID()和RAND(),不是复用同一个"默认值常量"。created_at三行显示相同,是因为三条INSERT在同一秒内真实执行完成,NOW()本身在这个精度上确实会给出相同结果,不代表它被当成了常量缓存。

结论:加一层括号,是MySQL区分"字面量"和"表达式"的真实标志

在MySQL 8.0.13之前,DEFAULT子句真实只接受字面量常量(数字、字符串),唯一的例外是DEFAULT CURRENT_TIMESTAMP这个专门为TIMESTAMP/DATETIME开的特例。8.0.13开始,只要把任意表达式真实用一对括号包起来(DEFAULT (expr)),MySQL就会把它当成一个每次插入都重新求值的表达式,而不是尝试把它解析成常量——这也是为什么本文的三个默认值都真实写成了DEFAULT (UUID())而不是DEFAULT UUID(),少了这对括号会被拒绝。这个特性真实让"插入时自动生成唯一标识"、"插入时自动打时间戳"这类逻辑不再需要依赖应用层代码或者触发器,直接在表定义里就能真实完成。

分步演示:三行插入,三组真实不同的默认值

每一步都是本文上面用真实INSERT跑出来的原始结果。

每一行真实都重新算了一次,不是复用常量
这一步新插入的行

    本文用到的工具

    • 本机 MySQL 26.7.0(InnoDB),DEFAULT (expr)语法(MySQL 8.0.13起支持)
    • 真实对比UUID()、NOW()、RAND()三种默认值表达式的逐行求值结果
    京ICP备2026067502号-1京公网安备11010502063487号