CREATE TABLE LIKE 只复制字段定义、索引、自增值、字符集和排序规则;不复制数据、外键、触发器、分区、注释(8.0.23+除外)、生成列或CHECK约束。

CREATE TABLE LIKE 会复制哪些结构?
CREATE TABLE new_table LIKE old_table 只复制表结构:字段定义、索引(包括主键、唯一键、普通 KEY)、自增起始值、字符集和排序规则。它**不复制**数据、外键约束、触发器、分区定义、注释(MySQL 8.0.23+ 才支持复制 COMMENT)、列的生成表达式(如 GENERATED ALWAYS AS)或 CHECK 约束(MySQL 8.0.16+ 的 CHECK 在 LIKE 中也不被复制)。
常见错误现象:DESCRIBE new_table 看起来一样,但插入数据时提示 Cannot add or update a child row: a foreign key constraint fails —— 因为外键没被复制,新表其实没约束,只是你误以为“完全一样”。
- 使用场景:快速建测试表、备份表结构、ETL 中准备空目标表
- 如果原表有
ENGINE=InnoDB,新表默认也是 InnoDB;但引擎类型本身不参与复制逻辑,只继承原表实际使用的引擎 - MySQL 5.7 和 8.0 行为一致,但 8.0.23+ 开始支持复制列注释,旧版本始终丢弃
为什么不能用 CREATE TABLE ... AS SELECT * FROM?
CREATE TABLE new_table AS SELECT * FROM old_table 看似更直观,但它本质是「查询结果集建表」,只保留字段名和类型(根据 SELECT 推断),**彻底丢失所有索引、主键、自增值、NOT NULL 约束(除非显式指定),甚至可能把 ENUM/SET 值转成字符串。
典型翻车点:原表 id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,用 AS SELECT 创建后变成 id INT 普通字段,无自增、无主键、可为 NULL —— 后续 INSERT 直接报错或数据错乱。
- 性能上,
AS SELECT还会执行一次全表扫描(即使加LIMIT 0,部分旧版 MySQL 仍会读取元数据并触发统计),而LIKE是纯 DDL,毫秒级 - 如果真想复制数据,应该分两步:
CREATE TABLE new_table LIKE old_table+INSERT INTO new_table SELECT * FROM old_table -
AS SELECT在需要改字段类型或过滤数据时才有价值,比如导出子集或做类型转换
复制结构后,如何补上外键和 CHECK 约束?
CREATE TABLE LIKE 不碰外键,必须手动重建。直接查 INFORMATION_SCHEMA.KEY_COLUMN_USAGE 或用 SHOW CREATE TABLE old_table 提取 CONSTRAINT 语句最可靠。
容易踩的坑:复制外键语句时忽略引用表是否存在、引擎是否匹配(如被引用表用了 MyISAM,InnoDB 外键会创建失败)、字符集是否一致(尤其跨库时),以及 ON DELETE/UPDATE 动作未显式写出导致默认为 RESTRICT,行为与原表不同。
- 先确认引用表已存在且结构兼容:
SELECT TABLE_NAME, ENGINE, TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('parent_table', 'new_table') - 从
SHOW CREATE TABLE old_table输出里复制类似CONSTRAINT `fk_name` FOREIGN KEY (`col`) REFERENCES `parent` (`id`) ON DELETE CASCADE的整行 - CHECK 约束同理,需手动
ALTER TABLE new_table ADD CONSTRAINT chk_x CHECK (status IN ('a','b')),MySQL 8.0.16+ 才支持
MySQL 8.0 下,LIKE 能否跳过某些索引?
不能。CREATE TABLE LIKE 是原子操作,要么全量复制索引,要么失败。没有 EXCLUDE INDEX 或类似语法。
如果你只需要结构但不要某个冗余索引(比如只为优化某条旧查询而建的单列索引),必须创建后再删:DROP INDEX idx_unwanted ON new_table。
- 删除索引前确认新表无写入,否则
DROP INDEX会锁表(MySQL 5.7+ 对大多数索引支持 ALGORITHM=INPLACE,但仍需元数据锁) - 如果原表有全文索引(
FULLTEXT),LIKE也会复制,但新表若未启用innodb_ft_enable_stopword等配置,可能影响后续搜索行为 - 分区表无法用
LIKE复制结构(MySQL 报错ERROR 1221 (HY000): Incorrect usage of TABLE and PARTITION),必须手写CREATE TABLE语句
真正麻烦的是跨版本迁移或带特殊存储引擎的表——LIKE 看似简单,但一旦涉及外键、分区、生成列、JSON 列默认值这些隐性依赖,光靠一条命令根本不够。得先看懂原表到底“有什么”,再决定补什么、删什么、调什么。










