create table ... select 会丢主键和索引,仅复制字段定义与数据,不保留主键、唯一索引、普通索引、auto_increment、外键、默认值、字符集等元信息;生产环境应分两步:先用 like 复制完整结构,再 insert into select 复制数据。

CREATE TABLE ... SELECT 会丢主键和索引,别直接用
这条语句看起来最省事:CREATE TABLE new_table SELECT * FROM old_table,但它只复制字段定义和数据,**不保留主键、唯一索引、普通索引、AUTO_INCREMENT、外键、默认值、字符集等元信息**。执行完后 DESCRIBE new_table 一看就明白——所有约束全没了。常见错误是后续插入失败(比如 NOT NULL 字段含空值)、自增列失效、查询变慢(没索引)。适合临时表或测试备份,生产环境慎用。
要完整结构,必须分两步:LIKE + INSERT INTO SELECT
这是生产环境首选方案,结构零丢失:
-
CREATE TABLE new_table LIKE old_table—— 完整继承引擎、字符集、排序规则、所有索引、主键、AUTO_INCREMENT属性 -
INSERT INTO new_table SELECT * FROM old_table—— 复制全部数据
大数据量时注意两点:
– 加事务控制:先 SET autocommit = 0,插完 COMMIT,避免长事务阻塞
– 分批插入:用 WHERE id BETWEEN ? AND ? 替代 LIMIT/OFFSET,避免偏移扫描性能衰减
跨库或超大表(千万行以上)优先用 mysqldump
本地复制小表用 SQL 命令足够,但跨实例、需保留建表注释、分区定义或触发器时,mysqldump 更可靠:
- 导出:
mysqldump -u user -p --single-transaction --quick db_name old_table > dump.sql - 导入前手动改表名,或用管道直传:
mysqldump -u src -p src_db old_table | mysql -u dst -p dst_db
关键参数:--single-transaction 保证 InnoDB 一致性快照,--quick 防止内存溢出;漏掉这两个,大表导出可能卡死或数据不一致。
别忽略字符集和 SQL mode 兼容性
即使命令执行成功,也可能出现乱码或隐式类型转换错误:
- 检查源表和目标库的
character_set_database和collation_database是否一致 - 两边
sql_mode差异会导致INSERT失败(比如 STRICT 模式下空字符串插入NOT NULL字段) - 用
SHOW CREATE TABLE old_table对比新旧表,确认ENGINE=、DEFAULT CHARSET=、COLUMN_FORMAT=等细节是否被意外修改
真正麻烦的不是复制动作本身,而是复制后表“看起来一样,用起来不对”——主键丢了、索引没生效、字符乱码、自增从1开始崩了。动手前先想清楚:你要的是临时快照,还是可上线的副本。











