不能。create table as select(ctas)只复制列定义、数据和not null约束,主键、索引、外键、默认值、自增属性、注释等全部丢失。

CREATE TABLE AS SELECT 能不能复制主键和索引?
不能。CREATE TABLE AS SELECT(CTAS)只复制列定义、数据和 NOT NULL 约束,其余全部丢失:主键、外键、索引、默认值、自增属性、注释、分区信息一概不保留。
如果你执行:
CREATE TABLE orders_bak AS SELECT * FROM orders;得到的
orders_bak 表结构干净但“裸奔”——查 SHOW CREATE TABLE orders_bak 就会发现所有约束和索引都消失了。- 主键不会自动创建,即使原表
id是主键 + 自增,新表里它只是普通INT列 -
DEFAULT值不会继承,哪怕原列定义是status TINYINT DEFAULT 0,新表里该列就是TINYINT无默认 - 字符集和排序规则通常继承自当前数据库默认值,不一定和源表一致(尤其跨库操作时)
想连结构带约束一起复制,该用什么替代方案?
用 CREATE TABLE ... LIKE + INSERT INTO ... SELECT 组合。
第一步建空表并完整复制结构:
CREATE TABLE orders_bak LIKE orders;这会拷贝主键、索引、默认值、自增、字符集、注释等所有 DDL 属性。
第二步导入数据:
INSERT INTO orders_bak SELECT * FROM orders;注意:如果目标表有自增主键且你希望保留原
id 值,需先执行 SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';,否则 MySQL 可能跳过显式插入的自增值。- 若源表有大量数据,考虑加
DISABLE KEYS(MyISAM)或调大innodb_buffer_pool_size(InnoDB)提升插入速度 - 如只需部分字段,
INSERT INTO ... SELECT的字段列表必须与CREATE TABLE ... LIKE的列顺序、类型兼容,否则报错 - 某些版本 MySQL 对
LIKE不支持临时表或视图,遇到ERROR 1146时请确认源表是基表
CTAS 在什么场景下反而更合适?
当你明确只需要“快照式”导出数据+基础结构,且后续要手动加约束或做清洗时,CTAS 更轻量、更可控。
典型用例:
• 快速生成测试表(比如从生产订单表抽 1000 行:CREATE TABLE orders_test AS SELECT * FROM orders LIMIT 1000;)
• 做 ETL 中间表(字段重命名、类型转换、过滤:CREATE TABLE sales_summary AS SELECT DATE(order_time) d, SUM(amount) s FROM sales WHERE status=1 GROUP BY 1;)
• 跨库迁移时规避源表锁(CTAS 是只读 SELECT,不阻塞源表写入)
- CTAS 默认使用
SELECT所见即所得,比如原表某列为GENERATED COLUMN,CTAS 会存计算后的值,而非表达式本身 - 如果源表含
JSON字段,CTAS 后仍是JSON类型;但含POINT等空间类型时,某些旧版 MySQL 可能降级为BLOB - 执行前建议先
EXPLAIN确认 SELECT 不会触发全表扫描以外的意外开销(比如隐式转换导致索引失效)
MySQL 8.0+ 有没有更省事的办法?
有,但仅限于克隆整个表(含数据、索引、约束、统计信息),用的是 CLONE PLUGIN,不是 SQL 语句,而是通过 CLONE LOCAL DATA DIRECTORY 或远程克隆实现。
它不走 SQL 解析器,直接拷贝物理页,速度极快,但要求:
• MySQL ≥ 8.0.17
• clone 插件已启用(INSTALL PLUGIN clone SONAME 'mysql_clone.so';)
• 源表引擎必须是 InnoDB
• 目标路径需有足够磁盘空间且 MySQL 进程有写权限
- 这不是 SQL 层功能,无法用在应用连接中动态调用,得用管理员账号在 MySQL 客户端执行
- 克隆后表名固定为原名加
@clone后缀,需手动RENAME,且不能指定新库名 - 它绕过了所有 SQL 层校验,所以如果源表本身有损坏(如二级索引不一致),克隆结果也会带病
真正需要“完全一致副本”的场景,别贪快用 CTAS,老实用 LIKE + INSERT;真要极致速度且环境达标,再评估 CLONE。最容易被忽略的是字符集和时区——哪怕结构复制对了,SELECT 时没设 SET NAMES utf8mb4 或没处理 TIMESTAMP 列的时区转换,数据就 quietly 变形了。











