CREATE TABLE AS SELECT 在 Oracle 里能复制结构和数据吗?
能,但默认只复制结构和数据,不复制主键、索引、约束、注释、默认值这些。很多人以为 CREATE TABLE new_tab AS SELECT * FROM old_tab 是“全量克隆”,结果一查 USER_CONSTRAINTS 就发现主键没了,外键断了,应用插入直接报错。
- 这个语句本质是“基于查询结果建表”,Oracle 只保留列名、数据类型(按实际值推断)、NOT NULL(仅当原列定义为 NOT NULL 且 SELECT 中未用表达式覆盖时才保留)
- 如果原表有
NUMBER(10,2),但某行值全是整数,CTAS可能生成NUMBER(精度丢失) DATE列没问题,但TIMESTAMP WITH TIME ZONE可能被降级成TIMESTAMP,时区信息丢掉
如何让新表带上主键和索引?
不能靠 CTAS 一步到位,得拆成两步:先建空表(含约束),再 INSERT。Oracle 没有像 PostgreSQL 的 CREATE TABLE ... LIKE ... INCLUDING ALL,得手动或脚本补。
- 用
DBMS_METADATA.GET_DDL('TABLE', 'OLD_TAB')拿到完整 DDL,改表名后执行——这是最稳的方式,能带主键、唯一约束、注释 - 如果只要主键和索引,别动约束,可以单独导出:
SELECT DBMS_METADATA.GET_DDL('CONSTRAINT', constraint_name) FROM USER_CONSTRAINTS WHERE table_name = 'OLD_TAB' AND constraint_type = 'P' - 索引要单独建:
SELECT DBMS_METADATA.GET_DDL('INDEX', index_name) FROM USER_INDEXES WHERE table_name = 'OLD_TAB',注意索引名可能冲突,新建前最好重命名
用 Data Pump(expdp/impdp)复制表时,哪些参数决定是否带约束?
expdp 默认不导出约束和索引,impdp 默认也不创建它们,除非显式指定。最容易踩的坑是只加了 CONTENT=DATA_ONLY 却忘了关掉 EXCLUDE=CONSTRAINT,INDEX 的默认行为。
- 要完整复制(结构+数据+约束+索引),导出时至少加:
EXCLUDE=STATISTICS(避免统计信息干扰),导入时加:TABLE_EXISTS_ACTION=REPLACE和REMAP_TABLE=old:new - 如果只想复制结构(不含数据),用
CONTENT=METADATA_ONLY,但记得加上INCLUDE=TABLE,CONSTRAINT,INDEX,否则还是空壳 QUERY参数只影响数据导出,不影响 DDL;如果用了QUERY="WHERE 1=0",数据不导,但约束和索引照常建——这点常被误认为“没生效”
SQL Developer 里右键“Copy to Another Schema”为什么有时缺字段注释?
图形界面背后调用的是 DBMS_METADATA,但它默认不包含注释(COMMENT ON COLUMN 不属于表对象的主 DDL)。即使勾了“Include constraints”“Include indexes”,注释也得额外处理。
- 注释得单独导:
SELECT 'COMMENT ON COLUMN ' || table_name || '.' || column_name || ' IS ''' || comments || ''';' FROM USER_COL_COMMENTS WHERE table_name = 'OLD_TAB' - 如果目标库字符集不是 AL32UTF8,中文注释可能变乱码,导出前确认
NLS_LANG设置和数据库字符集一致 - SQL Developer 21.4+ 版本在“Advanced Copy Options”里新增了 “Include column comments”,但只对新版本有效,老版本用户容易漏掉这层
复制表看着简单,但 Oracle 里真正保质保量地把约束、索引、注释、默认值、虚拟列、分区定义都搬过去,靠单条命令根本做不到。得看清楚你要的是哪一层——只是临时测试用数据?那 CTAS 够用;要上线替换?必须走 DBMS_METADATA + 手动补注释 + 验证约束状态。
