MySQL 默认表达式与生成列的迁移清单
把应用层的默认赋值迁到 MySQL 时,先不要把 DEFAULT (表达式) 和生成列当成同一种能力:前者只在插入时没有提供该列时补值,后者由其他列计算出结果,不能被应用写入任意覆盖。迁移清单应按“语义、表达式、存储、索引、回退”五项展开。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/
如果字段代表“缺省时的起始值”,用默认表达式;如果字段代表“由基础列决定的派生值”,用生成列。先保留基础列和旧客户端契约,再分阶段改 DDL。
先把默认表达式和生成列分成两条语义链
默认表达式服务于一次写入。下面的 created_at 和 attributes 在 INSERT 省略列名时才取默认值;调用方显式传值,默认值不会替换它。
CREATE TABLE order_item (
id BIGINT PRIMARY KEY,
qty INT NOT NULL,
unit_price DECIMAL(10, 2) NOT NULL,
-- 插入时未提供时间才使用当前时间
created_at DATETIME(6) NOT NULL DEFAULT (CURRENT_TIMESTAMP(6)),
-- JSON 字段的字面量默认值也要写成表达式
attributes JSON DEFAULT (JSON_OBJECT()),
-- 总价由基础列计算,禁止应用直接写入
total_amount DECIMAL(12, 2) AS (qty * unit_price) STORED,
-- 读取时计算的分类字段不额外占用列存储
price_band VARCHAR(12) AS (
CASE
WHEN unit_price >= 1000 THEN 'premium'
WHEN unit_price >= 100 THEN 'standard'
ELSE 'entry'
END
) VIRTUAL
);
MySQL 8.4 中,默认表达式通常用括号包住;TIMESTAMP 和 DATETIME 的 CURRENT_TIMESTAMP 有专门的省略括号规则。VIRTUAL 是生成列的默认存储方式,读取时计算;STORED 在插入或更新时计算并保存,适合需要持久化或建立索引的派生值。

迁移前先清点表达式的硬边界
默认表达式和生成列表达式都支持字面量、运算符以及一部分内置函数,但限制并不相同。生成列要求表达式使用确定性内置函数,不能放子查询、变量、存储函数或可加载函数;NOW()、CURRENT_USER() 等非确定函数不能直接作为生成列依据。
默认表达式也不能使用子查询、参数、变量、存储函数或可加载函数;如果依赖其他列,引用生成列或另一个表达式默认值时要注意列定义顺序,不能形成向前引用。BLOB、TEXT、GEOMETRY 和 JSON 的默认值还必须写成表达式,即使值本身只是一个字面量。
迁移时把以下内容写进设计单:基础列是否允许 NULL、表达式结果是否会发生类型转换、是否依赖 SQL mode、目标存储引擎是否支持表达式默认值、生成列是否需要索引,以及旧客户端是否仍会向派生列发送非 DEFAULT 值。
把迁移拆成可回退的 DDL 依赖
规模化迁移的瓶颈通常不是一条 DDL,而是旧应用、列定义和索引同时改变。建议先把“默认值迁移”和“派生列迁移”拆开,保留每一步的反向脚本。
-- 第一步:只调整新写入的缺省值,不回填历史行
ALTER TABLE order_item
MODIFY created_at DATETIME(6) NOT NULL
DEFAULT (CURRENT_TIMESTAMP(6)),
MODIFY attributes JSON DEFAULT (JSON_OBJECT());
-- 第二步:增加派生列,基础列仍由应用正常写入
ALTER TABLE order_item
ADD COLUMN total_amount DECIMAL(12, 2)
AS (qty * unit_price) STORED,
ADD INDEX idx_order_item_total_amount (total_amount);
-- 回滚脚本要单独保存,且只删除本次新增的对象
ALTER TABLE order_item
DROP INDEX idx_order_item_total_amount,
DROP COLUMN total_amount;
第一步不会把旧行的 created_at 改成新值;它影响的是之后省略该列的写入。第二步则会让生成列跟随基础列变化。若选择 VIRTUAL,读取时计算且不占列存储;InnoDB 可以为虚拟生成列建立二级索引。若选择 STORED,要把额外存储、写入计算和索引维护纳入容量与变更窗口评估。

上线前用清单确认应用契约没有断裂
- 确认 INSERT 省略列名、显式传值和写入
DEFAULT三种情况是否符合业务语义。 - 确认旧版本客户端不会给生成列发送业务值;生成列被显式写入时,允许的值只有
DEFAULT。 - 确认基础列的 NULL、精度、字符集和 SQL mode 不会让派生结果发生意外转换。
- 确认查询是否真的需要索引;STORED 列与索引会同时增加存储和写入维护成本。
- 确认
SHOW CREATE TABLE的结果已纳入迁移记录,并准备只撤销本次新增列和索引的回滚脚本。
尤其要留意依赖 DEFAULT() 的生成列表达式:修改基础列默认值可能改变生成列结果,MySQL 可能因此需要重建表。涉及这类依赖时,把 DDL 影响、锁等待和回滚窗口单独排进发布计划。
常见疑问
默认表达式能代替生成列吗? 不能。默认表达式只处理缺省输入,不能持续反映 qty 或 unit_price 的后续变化。
生成列应该优先选 VIRTUAL 还是 STORED? 不需要保存或索引时优先评估 VIRTUAL;需要稳定的物化值或索引时再选择 STORED,并计算额外存储和写入成本。
迁移后历史数据会被默认表达式回填吗? 不会。默认值只在对应写入缺少列值时生效;生成列则按其定义从基础列计算。
MySQL sys.schema_table_statistics_with_buffer 怎样定位表级 IO
- 上一篇
- MySQL sys.schema_table_statistics_with_buffer 怎样定位表级 IO
- 下一篇
- MySQL 事务隔离级别与锁定读的组合方案
-
- 数据库 · MySQL | 1小时前 |
- MySQL 不同字符集列的索引长度参数对比
- 118浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL Performance Schema 按线程聚合等待事件
- 306浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 事务隔离级别与锁定读的组合方案
- 271浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL sys.schema_table_statistics_with_buffer 怎样定位表级 IO
- 335浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL INFORMATION_SCHEMA.TABLES 怎样区分表大小与索引大小
- 175浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL CHECK TABLE 怎样判断表结构与索引是否正常
- 374浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL 分区表的分区裁剪条件设计
- 154浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL LAG 与 LAST_VALUE 窗口帧的结果边界
- 432浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL 窗口函数共享排序的 WINDOW 子句写法
- 232浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL SHOW CREATE TABLE 和 INFORMATION_SCHEMA 为什么看到的属性不同
- 287浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL CHECKSUM TABLE 怎样比较两张表的数据摘要
- 233浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- MySQL 8.4 ANALYZE TABLE 直方图的桶数量配置方法
- 417浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 816次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 807次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 899次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 870次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 693次使用
-
- MySQL JSON_TABLE 展开数组时如何保留缺失字段
- 2026-09-10 501浏览
-
- MySQL 分区表怎么处理跨分区唯一键:分区列约束与建表取舍
- 2026-08-30 501浏览
-
- MySQL权限管理设置全攻略
- 2026-03-29 501浏览
-
- MySQL分片实现方法及常见方案解析
- 2025-06-24 501浏览
-
- MySQL表空间碎片怎么清理?超详细优化教程
- 2025-06-13 501浏览

