用 CREATE TABLE ... LIKE 最稳,需加 INCLUDING ALL 才复制约束、索引等;CREATE TABLE AS 只复制数据和运行时类型,丢失约束默认值;Navicat“仅结构”导出易缺索引约束且顺序错乱,须手动勾选高级选项。
复制表结构:用 CREATE TABLE ... LIKE 最稳
navicat 本身不提供“右键→复制结构”的原子操作,直接点“复制”默认走的是数据导出流程。真正快速建空表(含约束、索引、默认值)得靠 sql:create table new_table (like old_table including all)。注意 including all 是关键——漏掉它就只复制列定义,丢掉索引、约束、注释甚至序列关联。
-
INCLUDING ALL在 PostgreSQL 9.5+ 支持;旧版本只能拆成INCLUDING CONSTRAINTS、INCLUDING INDEXES等逐项写 - 目标表名不能已存在,否则报错
ERROR: relation "new_table" already exists - 不会复制数据,也不会复制
OWNED BY的序列归属关系(比如 SERIAL 列绑定的 sequence),需要手动ALTER SEQUENCE ... OWNED BY
连数据一起复制:CREATE TABLE AS 要小心字段类型丢失
想结构+数据一步到位?CREATE TABLE new_table AS SELECT * FROM old_table 确实快,但它只保留查询结果的运行时类型,不继承原表的 NOT NULL、默认值、约束、索引——这些全没了。
- 如果原表有
id SERIAL PRIMARY KEY,新表里id只是普通integer,且允许 NULL -
SELECT *在有表达式或函数计算列时,会生成匿名列名(如?column?),建议显式写列名:SELECT id, name, created_at FROM old_table - 大数据量时,这个语句会锁源表读(取决于事务隔离级别),且没走 COPY 协议,比
COPY慢不少
Navicat 导出向导里“仅结构”选项的陷阱
Navicat 的“导出向导 → 格式选 SQL → 勾选‘仅结构’”看似省事,但生成的 SQL 默认不含索引和约束定义——它只导出 CREATE TABLE 主体,CREATE INDEX 和 ALTER TABLE ADD CONSTRAINT 被拆到后面,而且顺序可能错乱(比如先建外键再建被引用表)。
- 务必在导出前点开“高级”选项卡,勾上
Export indexes、Export foreign keys、Export check constraints - 导出后别直接执行:检查生成 SQL 中是否有跨 schema 引用(如
public.ref_table),Navicat 有时会漏写 schema 前缀,导致执行时报relation does not exist - 如果原表用了自定义类型(
CREATE TYPE),导出 SQL 不包含类型定义,需单独补上
带分区表或继承表时,LIKE 不递归
PostgreSQL 分区表(10+)或传统继承表,CREATE TABLE ... LIKE 只复制主表结构,不会自动创建子分区或继承关系。想完整复刻,必须分两步:先建主表(用 LIKE),再手动为每个子表执行同样操作,并补上 INHERITS 或 FOR VALUES 定义。
- 分区表元数据存在
pg_partitioned_table和pg_inherits里,不能靠 Navicat 可视化界面识别完整依赖 - 用
\d+ table_name在 psql 里看分区键和子表列表,比 Navicat 的“表属性”面板更可靠 - 如果子表上有独立索引或触发器,它们不会被
LIKE带走,得一个个重建
实际复制一个带高级特性的表,光靠 Navicat 点几下根本不够。约束、索引、分区、序列归属——这些细节都在 SQL 层面耦合着,漏掉任何一环,新表看着像,用起来立刻报错。











