CREATE TABLE ... LIKE 仅复制表结构,包括列定义、默认值、NULL约束、字符集、排序规则及主键/唯一键/普通索引(不复制约束名),但不复制数据、外键、触发器、注释、AUTO_INCREMENT值、分区定义等。

CREATE TABLE ... LIKE 会复制哪些东西
它只复制表结构,不复制数据、不复制索引以外的其他对象(比如触发器、外键约束、注释、AUTO_INCREMENT 值),也不复制分区定义(MySQL 8.0+ 对分区支持有限)。最关键的是:LIKE 不会继承 PRIMARY KEY 和 UNIQUE KEY 的自增属性——新表的 AUTO_INCREMENT 值默认为 1,哪怕原表是 10000。
- 复制:列定义、默认值(
DEFAULT)、NULL/NOT NULL、字符集、排序规则、主键/唯一键/普通索引(但不复制约束名) - 不复制:外键约束(
FOREIGN KEY)、触发器、存储过程关联、表注释(COMMENT)、行格式(ROW_FORMAT)、压缩设置、AUTO_INCREMENT当前值 - 注意:
LIKE在 MySQL 5.7 中不复制FULLTEXT索引;8.0+ 支持,但要求源表和目标表引擎一致(比如都是InnoDB)
为什么 CREATE TABLE ... LIKE 复制后插入失败
常见于带 NOT NULL 列但没设默认值的场景。原表可能靠应用层或触发器补值,而新表没这些逻辑,直接 INSERT INTO new_table SELECT * FROM old_table 就会报 Field 'xxx' doesn't have a default value。
- 检查新表字段是否全有默认值或允许 NULL:
SHOW COLUMNS FROM new_table - 如果原表有生成列(
GENERATED COLUMN),LIKE会复制,但 MySQL 5.7 不支持在SELECT *中直接引用它,需显式列出字段 - 字符集不一致也可能导致隐式转换失败,特别是从
utf8mb4复制到旧版本默认utf8表时
想连数据一起复制?别只用 LIKE
CREATE TABLE ... LIKE 本身不带数据,硬要“快速复制表”必须组合其他操作。最常用且安全的做法是两步:建结构 + 导数据。
- 先建空表:
CREATE TABLE new_table LIKE old_table - 再灌数据:
INSERT INTO new_table SELECT * FROM old_table - 如果要保留
AUTO_INCREMENT值,得手动改:ALTER TABLE new_table AUTO_INCREMENT = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'old_table') - 大表慎用
SELECT *:没加WHERE条件容易锁表或 OOM;建议分批或用mysqldump --no-create-info配合--skip-triggers
替代方案:CREATE TABLE AS SELECT(CTAS)的坑
CREATE TABLE new_table AS SELECT * FROM old_table 看似更“一步到位”,但它只复制列定义和数据,**完全不复制索引、主键、约束、默认值、字符集(用连接默认值)** —— 这和 LIKE 是本质区别。
- 结果表所有字段都变成
NULL允许,哪怕原表是NOT NULL - 主键和索引全丢,后续查起来慢,还可能引发唯一性问题
- 如果原表有
ENUM或SET,CTAS 可能转成VARCHAR,类型失真 - 真正需要“结构+数据”且不想写两行语句?老实用
mysqldump -d(结构)和-t(数据)拆开导,或 Percona Toolkit 的pt-archiver
最常被忽略的是:不同 MySQL 版本对 LIKE 的实现有细微差异,比如 5.6 不复制 CHECK 约束,8.0.16+ 才开始支持;线上迁移前务必在同版本环境验证索引是否真的建上了。










