【Oracle】ORA-14758: Last partition in the range section cannot be dropped

目录

1 软件环境

2 问题模拟

2.1 新建分区表

2.2 初始化数据

2.3 查看分区信息

2.4 删除分区P1

3 问题分析与解决

3.1 ORA ERR分析

3.2 问题解决


最近做数据库上线脚本的评审时,开发人员遇到了ORA-14758错误,本篇就针对这一错误进行分析,并给出解决方案。

1 软件环境

本实验的演示环境如下:

SQL> SELECT * from product_component_version;

PRODUCT VERSION STATUS
---------------------------------------- ---------- --------------------
NLSRTL 11.2.0.4.0 Production
Oracle Database 11g Enterprise Edition 11.2.0.4.0 64bit Production
PL/SQL 11.2.0.4.0 Production
TNS for Linux: 11.2.0.4.0 Production

2 问题模拟

按照如下步骤,创建数据库脚本,模拟ORA-14758错误。

2.1 新建分区表

SQL> create table t_interval
2 (
3 id number,
4 name varchar2(20),
5 cdate date default sysdate
6 )
7 partition by range(cdate)interval(numtodsinterval(1,'day'))
8 (
9 partition p1 values less than(to_date('2019-11-19','yyyy-mm-dd'))
10 );
Table created.

2.2 初始化数据

SQL> begin
2 for i in 1..10 loop
3 insert into t_interval values(i,'Test'||i,sysdate-2+i);
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.

2.3 查看分区信息

SQL> col table_name for a30
SQL> select table_name,partition_name,partition_position from user_tab_partitions
2 where table_name='T_INTERVAL';
TABLE_NAME PARTITION_NAME PARTITION_POSITION
------------------------------ ------------------------------ ------------------
T_INTERVAL P1 1
T_INTERVAL SYS_P41 2
T_INTERVAL SYS_P42 3
T_INTERVAL SYS_P43 4
T_INTERVAL SYS_P44 5
T_INTERVAL SYS_P45 6
T_INTERVAL SYS_P46 7
T_INTERVAL SYS_P47 8
T_INTERVAL SYS_P48 9
T_INTERVAL SYS_P49 10
10 rows selected.

2.4 删除分区P1

删除手工创建的第一个分区,出现ORA-14758错误,问题重现,为什么会出现这种错误呢?

SQL> alter table t_interval drop partition p1;
alter table t_interval drop partition p1
*
ERROR at line 1:
ORA-14758: Last partition in the range section cannot be dropped

3 问题分析与解决

针对上面的操作出现的ORA-14758错误,这里进行分析,首先查看引起该错误的原因以及解决办法。

3.1 ORA ERR分析

[oracle@strong ~]$ oerr ora 14758
14758, 00000, "Last partition in the range section cannot be dropped"
// *Cause: An attempt was made to drop the last range partition of an interval
// partitioned table.
// *Action: Do not attempt to drop this partition.

出现该错误,是因为不能删除最后一个分区,那么P1是新创建的第一个分区,为啥不可以删除呢,这里可以参考官网的说明:

You can also drop range partitions in an interval-partitioned table. The rules for dropping a range partition in an interval-partitioned table follow the rules for dropping a range partition in a range-partitioned table. If you drop a range partition in the middle of a set of range partitions, then the lower boundary for the next range partition shifts to the lower boundary of the range partition you just dropped. You cannot drop the highest range partition in the range-partitioned section of an interval-partitioned table.

也就是说,人工创建的分区P1是间隔分区中的最高分区,是自动产生其它分区的参照,故不能删除,当然,如果手工创建多个分区的话,最后一个手工分区是不可删除的,其它则可以删除,例如:

1)创建分区表

SQL> create table t_test
2 (
3 id number,
4 name varchar2(20),
5 cdate date default sysdate
6 )
7 partition by range(cdate)interval(numtodsinterval(1,'day'))
8 (
9 partition p1 values less than(to_date('2019-11-19','yyyy-mm-dd')),
10 partition p2 values less than(to_date('2019-11-20','yyyy-mm-dd'))
11 );
Table created.

2)初始化数据

SQL> begin
2 for i in 1..10 loop
3 insert into t_test values(i,'Test'||i,sysdate-3+i);
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.

3)查看分区信息

SQL> select table_name,partition_name,partition_position from user_tab_partitions
2 where table_name='T_TEST';
TABLE_NAME PARTITION_NAME PARTITION_POSITION
------------------------------ ------------------------------ ------------------
T_TEST P1 1
T_TEST P2 2
T_TEST SYS_P50 3
T_TEST SYS_P51 4
T_TEST SYS_P52 5
T_TEST SYS_P53 6
T_TEST SYS_P54 7
T_TEST SYS_P55 8
T_TEST SYS_P56 9
9 rows selected.
SQL> select * from t_test partition(P1);
ID NAME CDATE
---------- -------------------- ---------
1 Test1 17-NOV-19
2 Test2 18-NOV-19
SQL> select * from t_test partition(P2);
ID NAME CDATE
---------- -------------------- ---------
3 Test3 19-NOV-19

4)删除分区

SQL> alter table t_test drop partition p2;
alter table t_test drop partition p2
*
ERROR at line 1:
ORA-14758: Last partition in the range section cannot be dropped
SQL> alter table t_test drop partition p1;
Table altered.
SQL> alter table t_test drop partition SYS_P50;
Table altered.

由此可见,手工分区P1可以删除,P2不可以删除。

5)再次查看分区

SQL> select table_name,partition_name,partition_position from user_tab_partitions
2 where table_name='T_TEST';
TABLE_NAME PARTITION_NAME PARTITION_POSITION
------------------------------ ------------------------------ ------------------
T_TEST P2 1
T_TEST SYS_P51 2
T_TEST SYS_P52 3
T_TEST SYS_P53 4
T_TEST SYS_P54 5
T_TEST SYS_P55 6
T_TEST SYS_P56 7
7 rows selected.

可以看到,原来分区P1的POSITION是1,删除后,分区P2变成了1。

3.2 问题解决

那么如果想删除分区P2,该如何操作呢?可以通过将自动分区调整为普通的范围分区解决。

1)设置自动分区为普通范围分区

SQL> alter table t_test set interval();

Table altered.

2)查看修改后的分区信息

SQL> select table_name,partition_name,partition_position,interval from user_tab_partitions
2 where table_name='T_TEST';

TABLE_NAME PARTITION_NAME PARTITION_POSITION INT
------------------------------ ------------------------------ ------------------ ---
T_TEST P2 1 NO
T_TEST SYS_P51 2 NO
T_TEST SYS_P52 3 NO
T_TEST SYS_P53 4 NO
T_TEST SYS_P54 5 NO
T_TEST SYS_P55 6 NO
T_TEST SYS_P56 7 NO
7 rows selected.

可以看到,自动分区变为了普通的范围分区。

3)删除分区P2

SQL> alter table t_test drop partition p2;

Table altered.

这样就可以进行手工创建的分区的删除了。

4)设置普通分区为自动分区

SQL> alter table t_test set interval(numtodsinterval(1,'day'));

Table altered.

5)插入数据以验证自动分区

SQL> insert into t_test values(10,'Alen',sysdate+10);
1 row created.
SQL> commit;
Commit complete.
SQL> select table_name,partition_name,partition_position,interval from user_tab_partitions
2 where table_name='T_TEST';

TABLE_NAME PARTITION_NAME PARTITION_POSITION INT
------------------------------ ------------------------------ ------------------ ---
T_TEST SYS_P51 1 NO
T_TEST SYS_P52 2 NO
T_TEST SYS_P53 3 NO
T_TEST SYS_P54 4 NO
T_TEST SYS_P55 5 NO
T_TEST SYS_P56 6 NO
T_TEST SYS_P61 7 YES
7 rows selected.

可以看到,普通范围分区又被重置为了自动分区,原来的分区SYS_P56被置为最高分区用以作为自动生成分区的参照。

以上,就是ORA-14758问题的分析及解决,以及普通范围分区和自动分区的相互转换。

猜你喜欢

转载自blog.csdn.net/Alen_Liu_SZ/article/details/103152572