不能,CREATE TABLE AS SELECT只复制列定义和数据,完全丢失主键、索引、外键、约束、触发器等元数据;真正保留索引需分两步:先CREATE TABLE LIKE复制结构,再INSERT INTO SELECT导入数据。

不能。 CREATE TABLE AS SELECT(CTAS)语句在 MySQL 中完全不会复制原表的任何索引、主键、外键、约束或触发器,只复制数据和列定义(含数据类型、是否允许 NULL、默认值表达式等基础属性)。
为什么 CTAS 不保留索引?
因为 CTAS 的语义是「基于查询结果创建一张新表」,其本质等价于:
CREATE TABLE new_table (col1 TYPE, col2 TYPE, ...);<br>INSERT INTO new_table SELECT ... FROM old_table;
MySQL 在执行时只解析 SELECT 的输出列结构,不读取源表的元数据(如 KEY、PRIMARY KEY 信息)。这是 SQL 标准行为,不是 MySQL 的 bug。
如何真正保留索引(实操路径)
必须分两步:先建表结构(含索引),再导入数据。推荐用 CREATE TABLE LIKE + INSERT ... SELECT:
-
CREATE TABLE new_table LIKE old_table;—— 完整复制表结构、所有索引、约束、AUTO_INCREMENT 值 -
INSERT INTO new_table SELECT * FROM old_table;—— 导入数据(注意字段顺序和类型兼容性) - 若只需部分数据,可在
SELECT后加WHERE条件;若字段不一一对应,需显式列出列名
⚠️ 注意:LIKE 不复制数据,也不复制分区定义(MySQL 8.0+ 支持 CREATE TABLE ... LIKE 复制分区,但需确认版本)
常见错误现象与避坑点
直接用 CREATE TABLE new_table AS SELECT * FROM old_table; 后发现:
- 执行
SHOW INDEX FROM new_table;返回空结果 —— 索引确实没创建 - 查询变慢,尤其是按原主键字段
WHERE时 —— 因为没有索引支撑 - 后续手动
ADD PRIMARY KEY失败 —— 若原表有重复值或 NULL,而新表没设 NOT NULL,会报错ERROR 1062 (23000): Duplicate entry - 用
mysqldump --no-data导出原表 DDL 再改表名,看似可靠,但容易漏掉ENGINE、CHARSET或COMMENT等细节
最稳妥的做法永远是:先 CREATE TABLE LIKE,再 INSERT。如果原表极大且不能锁太久,考虑用 pt-online-schema-change 或分批插入,但核心逻辑不变——索引必须显式重建,没有捷径。


















