优先用 CREATE TABLE ... SELECT 快但不保约束,因按查询结果反推列定义,丢失主键、自增、索引、默认值及字符集;必须保结构时应选用 CREATE TABLE ... LIKE + INSERT INTO ... SELECT 组合。

想快速复制表结构和数据,优先用 CREATE TABLE ... SELECT;但只要表要写入、要查得快、要主键不冲突,就必须拆成 CREATE TABLE ... LIKE + INSERT INTO ... SELECT 两步。
为什么 CREATE TABLE new_t SELECT * FROM old_t 看似快却容易报错
它不是读原表元数据建表,而是“看查询结果长什么样,就照着画一张表”。所以:
• id 字段丢掉 AUTO_INCREMENT 和 PRIMARY KEY,插入时直接报 Field 'id' doesn't have a default value
• 原表的 UNIQUE KEY idx_email (email) 消失,重复邮箱能插进去
• 字符集可能从 utf8mb4_0900_as_cs 降级成 latin1_swedish_ci,中文乱码或排序异常
• 遇到 GENERATED COLUMN 或 CHECK 约束,语句直接失败退出
什么时候必须用 CREATE TABLE ... LIKE + INSERT
这是生产环境唯一能保主键、索引、自增值、NOT NULL、默认值、字符集的组合:
• CREATE TABLE new_t LIKE old_t 复制:所有索引(主键/唯一/全文)、AUTO_INCREMENT 当前值、DEFAULT、NOT NULL、字符集与排序规则
• 但它不复制:外键、触发器、表注释、分区定义
• 所以紧接着执行 INSERT INTO new_t SELECT * FROM old_t 时,必须确保字段顺序和类型严格一致;否则显式列出字段:INSERT INTO new_t (id, name) SELECT id, name FROM old_t
大表复制时最容易卡在哪儿
两步操作都可能被大表拖垮:
• CREATE TABLE ... LIKE 本身很快,但若目标库已存在同名表,直接报 ERROR 1050 (42S01): Table 'new_t' already exists
• INSERT INTO ... SELECT 是单事务,超大表会撑爆 innodb_log_file_size,触发长事务告警
• 若原表有外键引用其他表,而目标库还没建好被引用表,INSERT 会报 ERROR 1452 (23000): Cannot add or update a child row
• 不是所有“结构一致”都真一致:比如原表 DECIMAL(10,2) 在某些旧版本里被 SELECT 推导成 DOUBLE,数值精度就丢了
真正麻烦的不是语法,是字段兼容性、事务边界、外键依赖链和字符集继承逻辑——这些细节在 SHOW CREATE TABLE 里才看得清,别只信 DESCRIBE。


















