能否为未分区Oracle表添加列表分区?操作要求及报错排查
能否为未分区Oracle表添加列表分区?
可以,但需根据Oracle版本选择对应操作方式,同时满足特定要求。
核心要求
- 版本限制:Oracle 12c Release 1(12.1)及以上支持直接通过
ALTER TABLE语句转换;12c之前版本需借助在线重定义工具DBMS_REDEFINITION。 - 表结构约束:
- 不能是簇表、临时表、物化视图日志、索引组织表(IOT),也不能包含
LONG/LONG RAW类型列。 - 分区列必须是表中已存在的列,数据类型需支持列表分区(如
VARCHAR2、CHAR、NUMBER等)。 - 原表数据需能匹配到定义的分区值中,若存在未匹配数据,必须添加
PARTITION ... VALUES (DEFAULT)分区来容纳,否则转换会失败。
- 不能是簇表、临时表、物化视图日志、索引组织表(IOT),也不能包含
你的SQL语句错误原因
你执行的语句存在语法问题,Oracle中无法直接用ALTER TABLE ... MODIFY PARTITION BY完成转换,报错ORA-14006:无效的分区名称属于语法错误导致的误报(你的分区名称本身合法)。
正确操作方式
1. Oracle 12c及以上版本(直接转换)
使用带ONLINE选项的ALTER TABLE语句(ONLINE可选,允许转换期间表正常读写):
ALTER TABLE t1 MODIFY PARTITION BY LIST (c1) ( PARTITION c1a VALUES ('c1a'), PARTITION c1b VALUES ('c1b'), PARTITION c1c VALUES ('c1c'), PARTITION c1_default VALUES (DEFAULT) -- 用于容纳未匹配分区值的数据,必填(若原表存在此类数据) ) ONLINE;
2. Oracle 11g及以下版本(在线重定义)
需通过DBMS_REDEFINITION包分步完成:
- 创建与原表结构一致的列表分区空表:
CREATE TABLE t1_part PARTITION BY LIST (c1) ( PARTITION c1a VALUES ('c1a'), PARTITION c1b VALUES ('c1b'), PARTITION c1c VALUES ('c1c'), PARTITION c1_default VALUES (DEFAULT) ) AS SELECT * FROM t1 WHERE 1=0;
- 启动在线重定义:
BEGIN DBMS_REDEFINITION.START_REDEF_TABLE( uname => '你的用户名', orig_table => 't1', int_table => 't1_part' ); END; /
- 复制索引、触发器等依赖对象:
DECLARE error_count PLS_INTEGER := 0; BEGIN DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS( uname => '你的用户名', orig_table => 't1', int_table => 't1_part', copy_indexes => DBMS_REDEFINITION.CONS_ORIG_PARAMS, copy_triggers => TRUE, copy_constraints => TRUE, copy_privileges => TRUE, ignore_errors => TRUE, num_errors => error_count ); END; /
- 同步转换期间原表新增/修改的数据:
BEGIN DBMS_REDEFINITION.SYNC_INTERIM_TABLE( uname => '你的用户名', orig_table => 't1', int_table => 't1_part' ); END; /
- 完成重定义:
BEGIN DBMS_REDEFINITION.FINISH_REDEF_TABLE( uname => '你的用户名', orig_table => 't1', int_table => 't1_part' ); END; /
- 验证无误后删除临时表:
DROP TABLE t1_part;
内容的提问来源于stack exchange,提问作者mjsemina
相关产品推荐
相关产品推荐

