Oracle表增刪分區的腳本


一、前言

項目中的Oracle庫中有一張表(假設表名為Part_Tab),其中一列為Part_ID(int型),計划以該列作為分區依據。

通常Part_ID的值有較固定區間(假設為1~10),但特殊情況下可能超出此范圍;此外,其值並不連續。

根據業務,要求以存儲過程實現按照Part_ID增、刪分區的功能。

 

二、設計

1 根據需求,不宜采用list型分區,萬一刪除某個Part_ID后忘記了,又按這個Part_ID插入數據,就會產生運行錯誤。最終采用傳統的range型方式。

2 刪除分區沒有特別的難度,但在增加分區時,要考慮到如果Part_ID的值如果不比現有分區的range值都大,則不能簡單地add分區,而要把某個現有分區進行split。

3 確定split哪個具體分區時,依據是user_tab_partition視圖的high_value字段,但很不幸該字段為long類型,無法直接用在where條件中(報Ora-00997錯誤),雖然可轉換成number型,但過程卻十分麻煩(不能直接使用to_number,報Ora-00932錯誤)。

4 為此進行一點變通,將該表的分區名設定為:“表名_“||指定位數的PART_ID(這應該也是許許多多表分區名的傳統方法),再以user_tab_partition視圖的parttion_name進行判斷就方便多了。

 

三、建表腳本

--創建表按較固定的范圍創建初始分區
create
table PART_TAB ( PART_ID int not null, ... primary key (PART_ID, ...) ) PARTITION BY RANGE(PART_ID) ( PARTITION PART_TAB_01 VALUES LESS THAN (2) TABLESPACE ..., PARTITION PART_TAB_02 VALUES LESS THAN (3) TABLESPACE ..., PARTITION PART_TAB_03 VALUES LESS THAN (4) TABLESPACE ..., PARTITION PART_TAB_04 VALUES LESS THAN (5) TABLESPACE ..., PARTITION PART_TAB_05 VALUES LESS THAN (6) TABLESPACE ..., PARTITION PART_TAB_06 VALUES LESS THAN (7) TABLESPACE ..., PARTITION PART_TAB_07 VALUES LESS THAN (8) TABLESPACE ..., PARTITION PART_TAB_08 VALUES LESS THAN (9) TABLESPACE ..., PARTITION PART_TAB_09 VALUES LESS THAN (10) TABLESPACE ..., PARTITION PART_TAB_10 VALUES LESS THAN (11) TABLESPACE ..., );

 

四、刪除分區腳本

--存儲過程:刪除指定分區及數據
--如果該分區不存在則直接退出
create or replace procedure DROP_PART(pPartID in number) IS
  cnt       int;
  vPartName varchar2(20);
BEGIN
  vPartName := 'PART_TAB_' || trim(to_char(pPartID, '09'));
  select count(*) into cnt
    from USER_TAB_PARTITIONS
   where table_name = 'PART_TAB'
     and partition_name = vPartName;
  if cnt >= 1 then
    execute immediate 'alter table PART_TAB DROP PARTITION ' ||
                      vPartName;
  end if;
END;

五、增加分區腳本

--存儲過程:增加指定分區
--如果該分區已存在則直接退出
create or replace procedure ADD_PART(pPartID in number) IS
  cnt          int;
  vNewPartName varchar2(20);
  vOldPartName varchar2(20);
BEGIN
  vNewPartName := 'PART_TAB_' || trim(to_char(pPartID, '09'));
  select count(*) into cnt
    from USER_TAB_PARTITIONS
   where table_name = 'PART_TAB'
     and partition_name = vNewPartName;
  if cnt < 1 then
    --如果指定分區不存在,則繼續
    select min(partition_name) into vOldPartName
      from USER_TAB_PARTITIONS
     where table_name = 'PART_TAB'
       and partition_name > vNewPartName;
    if vOldPartName is null then
      --僅當新分區的Range值比全部已有分區的Range值時,直接增加分區
      execute immediate 'alter table PART_TAB ADD PARTITION ' ||
                        vNewPartName || ' values less than (' ||
                        to_char(pPartID + 1) || ')';
    else
      --否則,要把最接近的分區按Range值進行split
      execute immediate 'alter table PART_TAB SPLIT PARTITION ' ||
                        vOldPartName || ' AT (' || to_char(pPartID + 1) ||
                        ') into (PARTITION ' || vNewPartName ||
                        ', PARTITION ' || vOldPartName || ')';
    end if;
  end if;
END;

 

PS:腳本沒有考慮到表分區在不同表空間的情況(業務需求如此),加上也不難,對表空間名字做個類似限制即可,這里不再展開。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM