oracle增加分区的方法

本文介绍了一种在数据库中批量增加分区的有效方法。对于只有一级分区的情况,可以直接使用ALTER TABLE语句添加;而对于含有子分区的情况,则需要通过编写脚本的方式进行。脚本能够自动创建指定日期范围内的所有必要分区。

在项目中经常要增加大量的分区,总结了增加分区的方法:

1.如果只增加一级分区,没有子分区,可以简单的用如下语句增加:

alter table TDW_12580_ORD_REL_TAB_M
add PARTITION M_TDW_12580_201005 VALUES (201005)

[@more@]

2.如果增加的分区有子分区,则需要先建一个一级分区和子分区,然后用下面的脚本来增加:

注意:表名用大写,日期格式为20100801 结束日期为下一个月的1号,如20100901

脚本:

declare
--初始化参数
v_table_name varchar2(30);
v_partition_name varchar2(30);
v_subpartition_name varchar2(30);
v_segment_type varchar2(30);
v_begin_date_str varchar2(10);
v_sql varchar2(1000);
v_begin_date date;
v_end_date date;

--查找出所有分区表
cursor C_table_name is
select t1.table_name
from user_tables t1
where t1.table_name in ('&TABLE_NAME');
begin
open C_table_name;
loop
fetch C_table_name
into v_table_name;
exit when C_table_name%notfound;
--查找出分区表的类型
select distinct (t2.segment_type)
into v_segment_type
from user_segments t2
where t2.segment_name = v_table_name;
if v_segment_type in ('TABLE SUBPARTITION') then
--取出分区和子分区表名的不含日期部分
select distinct substr(t3.partition_name,
0,
length(t3.partition_name) - 6),
substr(t3.subpartition_name,
0,
length(t3.subpartition_name) - 8)
into v_partition_name, v_subpartition_name
from user_tab_subpartitions t3
where t3.table_name = v_table_name;
--初始化日期
v_begin_date := to_date('&START_DATE', 'YYYYMMDD');
v_end_date := to_date('&END_DATE', 'YYYYMMDD');
--循环创建2010年的表分区
while v_begin_date < v_end_date loop
--创建增加分区语句,如:alter table v_table_name add partition v_partition_nameYYYYMM values (YYYYMM) (subpartition v_subpartition_nameYYYYMMDD values (YYYYMMDD));
v_begin_date_str := substr(to_char(v_begin_date, 'YYYYMMDD'), 7, 2);
if v_begin_date_str in ('01') then
v_sql := 'alter table ' || v_table_name || ' add partition ' ||
v_partition_name ||
substr(to_char(v_begin_date, 'YYYYMMDD'), 0, 6) ||
' values (' ||
substr(to_char(v_begin_date, 'YYYYMMDD'), 0, 6) ||
') (subpartition ' || v_subpartition_name ||
to_char(v_begin_date, 'YYYYMMDD') || ' values (' ||
to_char(v_begin_date, 'YYYYMMDD') || '))';
else
v_sql := 'alter table ' || v_table_name || ' modify partition ' ||
v_partition_name ||
substr(to_char(v_begin_date, 'YYYYMMDD'), 0, 6) ||
' add subpartition ' || v_subpartition_name ||
to_char(v_begin_date, 'YYYYMMDD') || ' values (' ||
to_char(v_begin_date, 'YYYYMMDD') || ')';
end if;
--显示增加分区语句
--DBMS_OUTPUT.put_line(v_sql);
--执行增加分区语句
execute immediate v_sql;
--日期加一天
v_begin_date := v_begin_date + 1;
end loop;
elsif v_segment_type in ('TABLE PARTITION') then
--取出分区表名的不含日期部分
select distinct (substr(t4.partition_name,
0,
length(t4.partition_name) - 6))
into v_partition_name
from user_tab_partitions t4
where t4.table_name = v_table_name;
--初始化日期
v_begin_date := to_date('&START_DATE', 'YYYYMMDD');
v_end_date := to_date('&START_DATE', 'YYYYMMDD');
--循环创建2010年的表分区
while v_begin_date < v_end_date loop
--创建增加分区语句,如:alter table v_table_name add partition v_partition_nameYYYYMM values (YYYYMM);
v_sql := 'alter table ' || v_table_name || ' add partition ' ||
v_partition_name ||
substr(to_char(v_begin_date, 'YYYYMMDD'), 0, 6) ||
' values (' ||
substr(to_char(v_begin_date, 'YYYYMMDD'), 0, 6) || ')';
--显示增加分区语句
--- DBMS_OUTPUT.put_line(v_sql);
--执行增加分区语句
execute immediate v_sql;
--日期加一月
v_begin_date := add_months(v_begin_date, 1);
end loop;
else
DBMS_OUTPUT.put_line(v_table_name || '表类型为' || v_segment_type ||
',请查看!');
end if;
end loop;
close C_table_name;
end;

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7490392/viewspace-1039636/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7490392/viewspace-1039636/

<think> 我们被要求解决Oracle增加分区时出现ORA-14036错误的问题。根据引用[5]中提到的,这个错误发生在增加分区时,具体示例语句是: alter table sru_mx add partition P_DAT_SRU_MX_2009 values less than (to_date('2010-01-01','YYYY-MM-DD')) tablespace TBS_DAT_PAR_05; 错误ORA-14036的含义是:分区界限值高于最后一个分区的界限值。也就是说,在范围分区或间隔分区中,我们添加分区的界限值必须大于当前最后一个分区的界限值。 因此,解决步骤应该是: 1. 确认当前表的分区情况,尤其是最后一个分区的上限值(high_value)。 2. 确保我们要添加的新分区的界限值(在VALUES LESS THAN子句中指定的值)大于最后一个分区的high_value。 具体操作: 第一步:查询当前表的分区信息 我们可以使用以下SQL查询指定表的分区情况,特别是最后一个分区的high_value: ```sql SELECT partition_name, high_value FROM user_tab_partitions WHERE table_name = 'YOUR_TABLE_NAME' ORDER BY partition_position DESC; ``` 注意:将YOUR_TABLE_NAME替换为实际的表名。 第二步:确认最后一个分区的high_value 查询结果中,按照partition_position降序排列,第一条记录就是最后一个分区。注意high_value是一个字符串,需要转换理解(比如日期类型或者数字类型)。 第三步:添加分区 确保新分区的界限值大于最后一个分区的high_value。例如,如果最后一个分区的high_value是TO_DATE('2009-01-01','YYYY-MM-DD'),那么新分区的界限值至少应该是TO_DATE('2009-01-02','YYYY-MM-DD')或更大的日期(如果是日期分区)。如果是数字,则新分区的界限值必须大于最后一个分区的最大值。 举例: 假设最后一个分区的high_value是TO_DATE('2009-12-31','YYYY-MM-DD'),那么我们可以添加一个分区,界限值为TO_DATE('2010-01-01','YYYY-MM-DD'),如引用[5]中的例子。 但是,如果我们在执行引用[5]中的语句时报错,可能是因为最后一个分区的high_value已经大于或等于2010-01-01。例如,最后一个分区的high_value可能是TO_DATE('2010-01-01','YYYY-MM-DD'),那么再添加一个界限值为2010-01-01的分区就会报错,因为必须大于这个值。 因此,我们需要调整新分区的界限值,比如改为TO_DATE('2010-01-02','YYYY-MM-DD'),或者更常见的做法是使用一个更大的值,比如TO_DATE('2011-01-01','YYYY-MM-DD'),这样中间就不会有间隔。 另外,如果表是间隔分区(interval partitioning),我们通常不需要手动添加分区,因为Oracle会自动根据插入的数据创建分区。但如果我们确实需要手动添加,同样要遵循这个规则。 注意:在添加分区时,还应该考虑表空间等存储参数。 如果问题仍然存在,还需要检查分区键的数据类型是否正确,以及分区表是否有效。 总结:ORA-14036错误是由于新分区的界限值没有大于最后一个分区的界限值。通过调整新分区的界限值,使其大于最后一个分区的界限值,即可解决。 根据引用[5]的示例,我们可以推测用户可能是按照年份进行分区的,所以建议用户检查当前最后一个分区的年份上限,然后设置新分区为下一年度的开始。 例如,如果最后一个分区是2009年(上限是2010-01-01),那么下一个分区应该是2010年(上限2011-01-01)或者更晚。 因此,我们可以给出如下解决方案: ```sql -- 假设表名为YOUR_TABLE,最后一个分区的high_value是TO_DATE('2010-01-01','YYYY-MM-DD') -- 那么添加2010年的分区(实际存储2010年数据,分区界限为2011-01-01): ALTER TABLE YOUR_TABLE ADD PARTITION partition_name VALUES LESS THAN (TO_DATE('2011-01-01','YYYY-MM-DD')) TABLESPACE tablespace_name; ``` 注意:分区名称和表空间名称需要根据实际情况修改。 如果用户的分区是按照其他时间间隔(如月)或数字范围,同样需要确保新分区的界限值大于最后一个分区的界限值。 如果用户不确定最后一个分区的界限值,可以按照第一步中的查询获取。 此外,如果用户的分区表是间隔分区,那么手动添加分区可能不是最佳实践,建议让Oracle自动管理分区。但是,如果业务需要提前创建分区,则必须确保界限值大于当前最后一个分区的界限值。 最后,如果用户需要添加多个分区,可以使用多个ALTER TABLE ADD PARTITION语句,但每次添加都必须满足上述条件。 注意:在Oracle 11g及更高版本中,可以使用间隔分区(interval partitioning)来避免手动添加分区的麻烦。 如果用户遇到其他相关问题,比如分区索引失效(如引用[2]中的ORA-01502),则可能需要重建索引。 但是,当前问题只要求解决ORA-14036,所以我们先提供上述解决方案。 </think> ### ORA-14036 错误解决方案 在 Oracle 中执行 `ADD PARTITION` 操作时出现 **ORA-14036: partition bound must be higher than that of the last partition** 错误,表示新分区的边界值设置不当。以下是详细解决步骤: #### 1. **确认分区边界值** 首先查询现有分区的边界值,确保新分区边界值**严格大于**最后一个分区的边界值: ```sql SELECT partition_name, high_value FROM user_tab_partitions WHERE table_name = 'YOUR_TABLE_NAME' ORDER BY partition_position DESC; ``` *替换 `YOUR_TABLE_NAME` 为实际表名* **关键点**:新分区的 `VALUES LESS THAN` 值必须大于查询结果中最后一个分区的 `HIGH_VALUE`。 #### 2. **正确添加分区** 调整新分区边界值,确保其符合递增规则: ```sql -- 示例:添加 2010 年分区(边界设为 2011-01-01) ALTER TABLE sru_mx ADD PARTITION P_DAT_SRU_MX_2010 VALUES LESS THAN (TO_DATE('2011-01-01','YYYY-MM-DD')) TABLESPACE TBS_DAT_PAR_05; ``` **注意**: - 若最后一个分区边界是 `2010-01-01`,新分区边界至少需设为 `2010-01-02` 或更大。 - 日期格式必须与现有分区一致(如 `YYYY-MM-DD`)。 #### 3. **特殊场景处理** - **间隔分区表(Interval Partitioning)**: 此类分区通常无需手动添加分区。若必须手动操作,需禁用间隔属性: ```sql ALTER TABLE your_table SET INTERVAL (); -- 手动添加分区 ALTER TABLE your_table ADD PARTITION ... ; -- 重新启用间隔 ALTER TABLE your_table SET INTERVAL (NUMTOYMINTERVAL(1,'MONTH')); ``` - **分区索引失效**: 添加分区后检查索引状态: ```sql SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE_NAME'; ``` 若索引失效(`UNUSABLE`),需重建: ```sql ALTER INDEX your_index REBUILD; ``` #### 4. **表空间验证** 确保目标表空间有足够空间(避免引发 ORA-01653): ```sql SELECT tablespace_name, bytes/1024/1024 AS free_mb FROM dba_free_space WHERE tablespace_name = 'TBS_DAT_PAR_05'; ``` 若空间不足,需扩展: ```sql ALTER TABLESPACE TBS_DAT_PAR_05 ADD DATAFILE '/path/to/new_datafile.dbf' SIZE 2G; ``` #### 根本原因总结 ORA-14036 的本质是分区键值不满足**严格递增**规则。常见诱因包括: - 新分区边界值 ≤ 最后一个分区边界值 - 日期格式不一致(如 `DD-MM-YYYY` 与 `YYYY-MM-DD` 混用) - 间隔分区表未正确处理手动操作 --- ### 相关问题 1. 如何避免 Oracle 分区表出现 ORA-14400(分区键值超出范围)错误? 2. 分区索引失效(ORA-01502)后如何安全恢复? 3. Oracle 表空间扩展有哪些最佳实践? 4. 间隔分区(Interval Partitioning)与范围分区(Range Partitioning)有何区别? 5. 分区表数据迁移时如何保证分区键一致性? [^1][^2][^3][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值