oracle子分区表不支持subpartition级别的local unique索引,仅允许在一级分区级别创建local唯一索引,且索引列必须包含一级分区键;子分区字段的唯一性需依赖全局索引、应用层校验或复合主键实现。

Oracle子分区表不支持SUBPARTITION级别的LOCAL UNIQUE索引
Oracle根本不允许在子分区(subpartition)粒度上定义局部唯一索引。你执行类似 CREATE UNIQUE INDEX idx ON t(col) LOCAL SUBPARTITION TEMPLATE 或显式指定 SUBPARTITION 的语句,会直接报错 ORA-14039: partitioning column must be part of the unique key 或更底层的解析失败——因为语法本身就不被接受。
局部唯一索引只能建在分区(PARTITION)级别,且必须包含分区键
Oracle要求所有 LOCAL 唯一索引的列组合必须“覆盖”表的**一级分区键**(即 RANGE/LIST/HASH 分区列),而子分区(如 HASH-SUBPARTITION)只是物理存储切分,不参与逻辑唯一性校验。这意味着:
- 即使表是
RANGE-LIST或RANGE-HASH复合分区,唯一约束也只认最外层的 RANGE 列(比如sale_date) -
CREATE UNIQUE INDEX idx ON t(id, sale_date) LOCAL是合法的,因为sale_date是一级分区键 -
CREATE UNIQUE INDEX idx ON t(id) LOCAL一定失败,哪怕你在子分区里加了id和region组合也不行
想对子分区字段做唯一控制?只能靠应用层或全局索引
如果你的真实需求是在每个子分区内部强制某列唯一(例如每个 sale_date 分区下的每个 region 子分区中 device_id 不重复),Oracle 没有原生机制支持。常见应对方式包括:
- 用全局唯一索引:
CREATE UNIQUE INDEX idx ON t(device_id) GLOBAL,但会带来 DDL 风险和写入争用 - 在应用层插入前查重:
SELECT COUNT(*) FROM t WHERE sale_date = ? AND region = ? AND device_id = ? - 改用复合主键:
PRIMARY KEY(sale_date, region, device_id),并确保该组合能覆盖业务唯一性语义
注意:USING INDEX LOCAL 在复合分区表上仍只作用于一级分区段,子分区索引结构完全由 Oracle 自动管理,无法单独干预。
子分区操作不会触发局部索引失效,但也不能绕过一级分区键约束
执行 ALTER TABLE t SPLIT SUBPARTITION 或 EXCHANGE SUBPARTITION 时,局部索引不会变 UNUSABLE——这点和一级分区操作不同。但这不是因为子分区索引更“智能”,而是因为 Oracle 根本没把子分区当成独立的索引管理单元。所有约束、索引、统计信息的边界都止步于一级分区。所以别指望通过子分区设计来规避分区键强制要求,那条路语法上就不存在。











