【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問題的分析及解決,以及普通範圍分區和自動分區的相互轉換。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章