CREATE TABLE ... LIKE 仅复制表结构(字段、索引、主键、唯一约束),不复制数据、DEFAULT、CHECK约束、AUTO_INCREMENT值、注释;PostgreSQL需显式指定INCLUDING ALL等选项才能完整复制。
MySQL 用 CREATE TABLE ... LIKE 只能复制结构,不带数据
这个语句最常被误以为能“克隆表”,其实它只拷贝表定义:字段、类型、索引、约束(包括 primary key 和 unique),但完全忽略 default 表达式、check 约束(mysql 8.0.16+)、自增初始值(auto_increment 值不会继承),更不会复制任何一行数据。
常见错误现象:SHOW CREATE TABLE new_table 看起来一模一样,但插入数据时报 Field 'xxx' doesn't have a default value —— 因为原表的 DEFAULT 没被复制过去。
- 适用场景:快速建一个空壳表用于测试或临时分析,且你确认不需要默认值或检查约束
- 注意
AUTO_INCREMENT:新表的自增值从 1 开始,不是原表当前值;如需继承,得手动ALTER TABLE new_table AUTO_INCREMENT = N - 不复制注释:字段
COMMENT和表注释全部丢失
PostgreSQL 用 CREATE TABLE ... (LIKE ...) 支持细粒度控制
PostgreSQL 的 LIKE 子句比 MySQL 强得多,但默认行为也容易踩坑:它默认不复制 DEFAULT、IDENTITY、GENERATED 列,甚至索引都得显式声明。
正确写法必须带选项,比如:
CREATE TABLE new_table (LIKE old_table INCLUDING ALL);
INCLUDING ALL 是关键,它等价于 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS。漏掉任意一项,就可能丢东西。
- 最容易忽略的是
INCLUDING IDENTITY:如果原表有GENERATED ALWAYS AS IDENTITY列,不加这句,新表该列会变成普通INT,无法自动递增 -
INCLUDING INDEXES复制的是索引定义,不是索引数据;建完表后仍需VACUUM或等 autovacuum 清理旧表残留 - 不支持复制
FOREIGN KEY引用关系(即不会自动建外键约束),需要额外ALTER TABLE ... ADD CONSTRAINT
想连数据一起复制?INSERT INTO ... SELECT 是通用解法
无论 MySQL 还是 PostgreSQL,只要目标表结构已存在(不管怎么建的),往里灌数据都靠这条语句。但它不是“一键克隆”,而是分两步走:先建表,再插数据。
常见错误现象:字段顺序不一致导致值错位、类型隐式转换失败、大表卡死、事务锁表太久。
- 务必显式列出字段名:
INSERT INTO new_table (col1, col2) SELECT col1, col2 FROM old_table;别用SELECT *,否则字段顺序或新增列会导致错配 - 大表慎用:MySQL 默认单事务执行,可能撑爆
innodb_log_file_size;建议分批次,比如加WHERE id BETWEEN ? AND ? - PostgreSQL 中,如果原表有
serial或identity列,目标表对应列要设为NOT NULL,否则INSERT会因序列未触发而报错
真正“完整克隆”往往要组合操作,没有银弹
所谓“完整”,得看你要保留什么:结构、约束、索引、默认值、注释、权限、数据、自增/序列当前值、外键引用关系……每多一项,工具链就复杂一分。
mysqldump 和 pg_dump 是最接近“完整”的方案,但它们导出的是 SQL 文本,不是实时命令;直接执行可能因字符集、SQL 模式、权限不足而失败。
- MySQL:用
mysqldump --no-data db table | mysql db -o new_table建结构,再mysqldump db table | mysql db导数据;但--no-create-info和--skip-triggers得按需加,否则可能混入触发器或视图 - PostgreSQL:
pg_dump --schema-only --table=old_table db > struct.sql,再手动替换表名,再psql db ;数据用 <code>pg_dump --data-only --table=old_table db - 权限和所有者不会自动继承,
pg_dump加--no-owner是为了防止恢复时因用户不存在失败,但也意味着你得自己ALTER TABLE ... OWNER TO
真正麻烦的从来不是语法,而是你根本没想清楚——到底哪些东西算“必须保留”。比如测试环境克隆,索引和统计信息反而该删掉;而生产迁移,序列值和外键完整性一点都不能差。










