ORA-14097 根源是 Oracle 严格按 sys.col$ 字典中 column_id、类型、精度、空值性、隐藏/未使用列、默认值及约束等字节级比对,任一差异即报错;须用 user_tab_columns 等字典视图逐项核验并重建交换表。
ora-14097 报错不是“类型看起来像但不匹配”,而是 oracle 在底层字典(比如 sys.col$)里逐字段比对时发现硬性不一致——哪怕只是字段顺序、默认值、隐藏属性或未使用列状态不同,都会直接拒绝交换。
检查两个表的字段顺序和数量是否完全一致
字段顺序错一位就报 ORA-14097,CREATE TABLE AS SELECT * 生成的中间表经常出这个问题。Oracle 不看语义等价,只按列在 user_tab_columns.column_id 中的物理顺序严格比对。
- 用
SELECT column_name, column_id FROM user_tab_columns WHERE table_name = 'YOUR_TABLE' ORDER BY column_id分别查源分区表和交换表,逐行对比column_id和column_name - 特别注意:即使所有字段名、类型、长度都一样,只要中间表是用
SELECT a,b,c FROM src建的,而源表定义是c,a,b,就必然失败 - 修复方式不是改 SQL,而是重建交换表:用源表的 DDL(从
DBMS_METADATA.GET_DDL获取)完整执行,不要手写或依赖 CTAS
验证字段类型、精度、空值约束是否字节级一致
看似相同的 VARCHAR2(32) 可能因字符集语义或隐式转换被记录为不同 internal type;NOT NULL 约束缺失也会触发该错误——CTAS 不继承约束。
- 查
data_type、data_length、data_precision、nullable四个字段:SELECT column_name, data_type, data_length, data_precision, nullable FROM user_tab_columns WHERE table_name IN ('SRC_TAB', 'EXCH_TAB') ORDER BY table_name, column_id -
CHARvsVARCHAR2、NUMBERvsNUMBER(10)、带/不带NOT NULL都算不一致 - 如果发现某列
nullable = 'Y'而源表是'N',需显式加约束:ALTER TABLE exch_tab MODIFY (col_name NOT NULL)
排查隐藏列、未使用列和 default 属性差异
这些不会出现在 DESC 或常规 DDL 里,但 Oracle 内部会校验。常见于分区后新增字段、启用压缩、或执行过 DROP COLUMN 但没清理未使用列。
- 查未使用列:
SELECT column_name FROM user_tab_cols WHERE table_name = 'XXX' AND hidden_column = 'YES' OR virtual_column = 'YES' OR unused_col_count > 0 - 确认是否有隐藏列(如压缩表自动添加的
SYS_NC*列)或虚拟列;有则必须在交换表中也存在同名同属性列 - 执行
ALTER TABLE xxx DROP UNUSED COLUMNS清理源表和交换表中的残留未使用列(注意:该操作会锁表,生产慎用) - default 值不一致也可能导致底层
col$.property字段值不同——哪怕都是NULL,存储方式可能不同;最稳妥是统一去掉 default:ALTER TABLE xxx MODIFY col_name DEFAULT NULL
主键、索引和约束必须镜像,不能只看数据结构
ORA-14097 会连带校验约束元数据。分区表若有主键,交换表对应列必须有相同名称、类型、且已启用主键约束(不仅仅是唯一索引)。
- 查主键:
SELECT cols.column_name FROM user_constraints cons, user_cons_columns cols WHERE cons.constraint_name = cols.constraint_name AND cons.constraint_type = 'P' AND cons.table_name = 'XXX' - 如果源表主键是
(id),交换表必须执行ALTER TABLE exch_tab ADD PRIMARY KEY (id),仅建唯一索引不够 - 外键、check 约束也要一致;若不想重建,可临时禁用(
DISABLE NOVALIDATE),但需确保业务逻辑允许 - 交换时务必加
EXCLUDING INDEXES,否则可能叠加 ORA-14098(索引不匹配)
真正棘手的 ORA-14097 往往卡在你看不见的地方:col$.property 值异常、隐藏列残留、甚至分区表在某个补丁版本下因 BUG 记录了不一致的 internal flags。不要只盯着 DDL 表面,优先用字典视图做逐字段比对,再考虑重建或事件绕过——后者仅限测试环境验证,生产上宁可停机重建小表,也不要赌一个 trace event 的稳定性。


















