mysql用create table ... like + insert into ... select最稳:like只复制结构(含索引、约束),不带数据;需补insert语句才能复制数据,否则新表为空壳。
mysql 用 create table ... like + insert into ... select 最稳
直接复制表结构和数据,create table new_table like old_table 只拷贝结构(含索引、约束),不带数据;要连数据一起搬,必须补一句 insert into new_table select * from old_table。漏掉后半句,新表就是空壳,看着像备份,实则没用。
常见错误现象:SHOW CREATE TABLE new_table 看起来一模一样,但 SELECT COUNT(*) 返回 0 —— 就是只执行了 LIKE 那步。
- 如果原表有自增主键,新表的
AUTO_INCREMENT值默认从 1 开始,不是继承原表当前值;需要手动ALTER TABLE new_table AUTO_INCREMENT = N - 外键约束不会被
LIKE复制,得自己加ADD CONSTRAINT - 触发器、存储过程、注释字段(
COMMENT)也不在LIKE范围内
PostgreSQL 用 CREATE TABLE ... AS 一行搞定但有陷阱
CREATE TABLE new_table AS TABLE old_table 确实能同时复制结构和数据,但它不复制主键、索引、默认值、约束 —— 这些全得手补。很多人以为“AS TABLE”等于完整克隆,结果新表查得慢、插不了重复值、甚至主键失效。
使用场景:临时导出快照、ETL 中间表、测试数据生成。不适合做生产级备份表。
- 想保留主键?得额外
ALTER TABLE new_table ADD PRIMARY KEY (id) - 索引必须单独建:
CREATE INDEX ON new_table (created_at) - 如果原表有
GENERATED列或IDENTITY列,AS TABLE会转成普通列,失去自增行为
SQL Server 用 SELECT INTO 简单但不支持约束继承
SELECT * INTO new_table FROM old_table 是最直觉的写法,但它只复制数据类型和 NULL 属性,所有约束、索引、主键、默认值、标识属性(IDENTITY)全丢光。尤其要注意:如果原表 id 是 IDENTITY(1,1),新表的 id 就只是个普通 INT,再插入会报错或覆盖。
性能影响:SELECT INTO 是最小日志操作(bulk-logged),速度快,但不可回滚,且不能在事务里用(除非数据库设为 full recovery 并显式加日志)。
- 恢复标识列?得
SET IDENTITY_INSERT new_table ON再插入,之后关掉 - 主键要手动加:
ALTER TABLE new_table ADD CONSTRAINT pk_new PRIMARY KEY (id) - 没有
LIKE对应物,真要拷约束,只能靠sys视图查定义再拼 DDL
跨库/跨实例克隆时,别信图形界面的「备份表」按钮
很多 GUI 工具(如 DBeaver、Navicat、phpMyAdmin)点一下「复制表」看似方便,但底层可能只跑 CREATE TABLE ... LIKE 或 SELECT INTO,不提示你缺索引、没主键、丢注释。更糟的是,某些版本对 TEXT/JSON 字段类型处理错位,或把 TIMESTAMP 默认值转成字符串。
容易踩的坑:工具自动加了 IF NOT EXISTS,但没检查同名视图/临时表冲突;或者用 mysqldump --no-data + --data-only 分两步导,中间表结构改了就不同步。
- 关键字段(如
created_at DEFAULT CURRENT_TIMESTAMP)务必人工核对SHOW CREATE TABLE输出 - 大表克隆前先
SET SESSION sort_buffer_size = 268435456(256MB),避免磁盘临时表拖慢 - 如果目标库字符集不同(比如原库
utf8mb4_0900_as_cs,新库还是utf8mb4_general_ci),排序规则差异会导致索引失效,得显式指定COLLATE
真正可靠的克隆,永远是从 DDL 定义出发:先取结构(带约束),再导数据(带类型映射),最后补索引和权限。省掉任何一步,都可能让新表在某个查询、某个并发写入、某次迁移时突然卡住。










