最快方式是create table...select,但会丢失主键、索引、自增等元信息;完整保留结构需分两步:先create table...like复制结构,再insert into...select插入数据。

直接用 CREATE TABLE ... SELECT 最快,但会丢主键、索引、自增属性——别急着执行,先看清楚你要保留什么。
复制结构+数据但不保留约束时用 CREATE TABLE ... SELECT
这是最简方式,一条语句搞定,适合临时表、测试备份或字段完全兼容的轻量场景:
-
CREATE TABLE new_table SELECT * FROM old_table;—— 复制全部字段和数据,但新表没有主键、索引、AUTO_INCREMENT、外键等元信息 - 加
WHERE可筛选:比如只复制最近一周数据:CREATE TABLE new_table SELECT * FROM old_table WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY); - 如果源表太大(比如超百万行),这条语句可能长时间持有表级锁(尤其 MyISAM);InnoDB 下虽支持行锁,但全表扫描仍可能阻塞写入
- 字段别名会被继承,但类型可能被隐式转换(如
VARCHAR(255)在结果集中可能变成TEXT),需检查新表DESCRIBE new_table;
要完整保留主键/索引/自增属性,必须分两步:CREATE TABLE ... LIKE + INSERT INTO ... SELECT
这是生产环境推荐做法,结构零丢失,但操作多一步:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 先完整复制结构:
CREATE TABLE new_table LIKE old_table;—— 主键、唯一索引、普通索引、AUTO_INCREMENT、默认值、字符集、排序规则全部原样继承 - 再插入数据:
INSERT INTO new_table SELECT * FROM old_table; - 大数据量时务必分批插入,避免事务过大或锁表:
INSERT INTO new_table SELECT * FROM old_table LIMIT 10000 OFFSET 0;,然后循环递增OFFSET(注意OFFSET越大越慢,更推荐用主键范围分片,如WHERE id BETWEEN 1 AND 10000) - 如果目标表有
NOT NULL字段但源表对应列含NULL,INSERT会失败,需提前处理或加IFNULL()
跨库复制或需要导出再导入时,优先用 mysqldump
当目标表在另一个实例、或你希望保留建表语句原始格式(含注释、分区定义等),mysqldump 更可靠:
- 导出结构+数据:
mysqldump -u user -p db_name old_table > old_table.sql - 导入到同库新表:编辑
old_table.sql,把CREATE TABLE `old_table`替换为CREATE TABLE `new_table`,再执行mysql -u user -p db_name - 跨库直传(不落地文件):
mysqldump -u src_user -p src_db old_table | mysql -u dst_user -p dst_db—— 注意两边字符集、SQL mode 必须一致,否则可能乱码或报错 -
mysqldump默认带INSERT语句,对大表恢复慢;加--skip-extended-insert可减少日志体积,但单条INSERT更易中断重试
目标表已存在且结构匹配,直接用 INSERT INTO ... SELECT
这是唯一适用于“往已有表里追加数据”的方式,不创建新表:
- 字段顺序和类型必须严格兼容,否则报错:
INSERT INTO existing_table SELECT * FROM old_table; - 显式指定字段更安全:
INSERT INTO existing_table (id, name, created_at) SELECT id, name, created_at FROM old_table;—— 避免因字段增减或顺序变化导致错位 - 如果存在主键/唯一键冲突,加
ON DUPLICATE KEY UPDATE或用INSERT IGNORE控制行为 - 目标表若有触发器,
INSERT ... SELECT会触发;而CREATE TABLE ... SELECT不会触发源表触发器,也不会在新表上自动创建触发器
真正容易被忽略的点是字符集和排序规则——LIKE 和 SELECT 都继承源表定义,但如果源表本身字符集混乱(比如表用 utf8mb4、字段却用 latin1),复制后问题照旧。动手前先查:SHOW CREATE TABLE old_table;,确认 CHARACTER SET 和 COLLATE 一致再操作。










