ORA-14098是索引元数据校验失败,非数据问题;要求非分区表的每个非分区索引必须有完全等价的LOCAL索引在分区表上,包括列数、顺序、类型、长度、可空性、排序方向、压缩及函数表达式均一致。
ORA-14098根本不是数据问题,而是索引元数据校验失败
这个错误从不因为数据内容报错,只因 oracle 在 alter table exchange partition 前强制比对两张表的索引定义是否“字节级一致”。哪怕只是索引名不同、列顺序调换、或一个用了 compress 一个没用,都会触发 ora-14098: index mismatch for tables in alter table exchange partition。
关键点在于:Oracle 要求——
- 非分区表上的每个非分区索引,必须有**完全等价的 LOCAL 索引**在分区表上(不能是 GLOBAL)
- “完全等价”指:索引列数量、顺序、数据类型、长度、可空性、排序方向(ASC/DESC)、压缩设置、函数表达式(如有)全部相同
- 索引名可以不同,但列定义和结构必须镜像
检查本地索引是否真正一致:别只看列名
很多人执行 SELECT index_name, column_name FROM user_ind_columns WHERE table_name IN ('T1','T2') ORDER BY index_name, column_position; 就以为齐活了,其实漏掉关键维度:
- 确认分区表索引确实是
LOCAL:查user_indexes.index_type,值必须是LOCALE INDEX,不是FUNCTION-BASED NORMAL或GLOBAL - 检查列是否隐式转换:比如分区表索引建在
TO_CHAR(id)上,而交换表索引建在裸列id上 → 不匹配 - 验证
column_length:VARCHAR2(50)和VARCHAR2(100)视为不一致,即使实际数据都没超长 - 留意排序方向:
CREATE INDEX i ON t(x ASC, y DESC)和CREATE INDEX j ON t(x ASC, y ASC)不等价
修复时优先删索引,而不是改索引
试图用 ALTER INDEX ... REBUILD LOCAL 修已有索引,常因元数据残留失败。更可靠的做法是清零重来:
- 先删掉分区表上所有疑似有问题的 LOCAL 索引:
DROP INDEX idx_part_table_col; - 再删掉非分区表上的对应索引:
DROP INDEX idx_nonpart_col; - 用完全相同的 DDL 重建两者(复制粘贴同一段 SQL,仅改表名):
CREATE INDEX idx_part_table_col ON part_table(col1, col2) LOCAL TABLESPACE ts_idx;
CREATE INDEX idx_nonpart_col ON nonpart_table(col1, col2) TABLESPACE ts_idx;
注意:两个语句中 col1, col2 顺序、大小写、括号位置、TABLESPACE 名称都必须一致;LOCAL 只加在分区表语句里,非分区表语句里不能写。
实在对不齐?用 EXCLUDING INDEXES 绕过校验
如果业务允许交换后手动重建索引(比如夜间维护窗口充足),最省事的解法是跳过索引校验环节:
- 去掉
INCLUDING INDEXES,直接执行:ALTER TABLE part_table EXCHANGE PARTITION p1 WITH TABLE nonpart_table WITHOUT VALIDATION; - 交换完成后,立刻重建分区表的 LOCAL 索引:
ALTER INDEX idx_part_table_col REBUILD PARTITION p1; - 非分区表的索引按需重建或丢弃,它之后就是个空壳表了
这个方案避开了所有索引结构比对逻辑,但代价是交换后局部索引对应分区会变成 UNUSABLE 状态,必须显式 REBUILD 才能用——这点常被忽略,导致后续查询走全表扫描。


















