分區

數據庫每年都會新增n個各種類型的分區,手動編寫工作量巨大且容易出錯。下面說一下當前的腳本實現。
首先有一個存儲這些信息的表。

屬性名稱

類型

備註

OBJ_NAME

VARCHAR2(255)

操作對象名(表或索引)

PARTITION_PRE_NAME

VARCHAR2(255)

分區名前綴

TBS_NAME

VARCHAR2(255)

表空間名

P_FLG

VARCHAR2(10)

分區範圍(月天)

P_TYPE

VARCHAR2(10)

分區類型(hash range list)

D_NUM

NUMBER

按天分區則需設置按多少天一個分區

IS_CREATE_SCRIPT

NUMBER

是否需要生成分區腳本(1生成0不需生成)

CREATE_START_TIME

VARCHAR2(20)

分區開始時間

CREATE_END_TIME

VARCHAR2(20)

分區結束時間

CREATE_DEAD_LINE

VARCHAR2(20)

當前已創建分區截止時間

OP_TYPE

VARCHAR2(20)

操作類型(ADD /SPLIT)

SPLIT_PAR_NAME

VARCHAR2(255)

待拆分的分區

OBJ_TYPE

VARCHAR2(20)

操作對象類型(TABLE/INDEX)

這裏面的操作類型有兩個一個是add另外一個是split,這是因爲我們在創建索引的時候有寫需要指定一個最大的區間值,下次再擴展的時候就需要split最大的分區塊。
在上面的表中,我們維護了自己數據庫中需要創建索引的具體信息值。
然後只需要執行下面的存儲過程即可以生成相應的分區腳本了。

?

create or replace procedure add_additional_partition2 is
  str varchar2(8000);
  dtr varchar2(4);
  j   number default 0;
  i   number default 0;
 
  start_date date;
  end_date   date;
  cur_date   date;
 
  str_cur_date varchar2(20);
  par_name     varchar2(100);
 
  tbsname             varchar2(100);
  objname             varchar2(100);
  curobjname          varchar2(100);
  pre_name            varchar2(100);
  flg                 varchar2(100);
  ptype               varchar2(100);
  pdaynum             number;
  pnumber             number;
  optype              varchar2(20);
  objtype             varchar2(20);
  splitparname        varchar2(255);
  v_create_start_time varchar2(20);
  v_create_end_time   varchar2(20);
 
  CURSOR C_PARTITION_TABLE IS
    SELECT OBJ_NAME,
           PARTITION_PRE_NAME,
           TBS_NAME,
           P_FLG,
           P_TYPE,
           D_NUM,
           CREATE_START_TIME,
           CREATE_END_TIME,
           OP_TYPE,
           SPLIT_PAR_NAME,
           OBJ_TYPE
      FROM GE_T_PARTITION_INFO
     WHERE IS_CREATE_SCRIPT = 1;
 
begin
   
  dbms_output.enable(999999999999999999999);
  dtr := '';
 
  FOR R_PAR_TABLE IN C_PARTITION_TABLE LOOP
 
 
    tbsname             := R_PAR_TABLE.TBS_NAME;
    objname             := R_PAR_TABLE.OBJ_NAME;
    pre_name            := R_PAR_TABLE.PARTITION_PRE_NAME;
    v_create_start_time := R_PAR_TABLE.CREATE_START_TIME;
    v_create_end_time   := R_PAR_TABLE.CREATE_END_TIME;
    flg                 := R_PAR_TABLE.P_FLG;
    ptype               := R_PAR_TABLE.P_TYPE;
    pdaynum             := R_PAR_TABLE.D_NUM;
    pnumber             := R_PAR_TABLE.D_NUM;
    optype              := R_PAR_TABLE.OP_TYPE;
    splitparname        := R_PAR_TABLE.SPLIT_PAR_NAME;
    objtype             := R_PAR_TABLE.OBJ_TYPE;
    start_date          := to_date(v_create_start_time,'yyyy-MM-dd hh24:Mi:ss');
    end_date            := to_date(v_create_end_time,'yyyy-MM-dd hh24:Mi:ss');
 
    if curobjname is null then
       curobjname := objname;
    elsif curobjname is not null and curobjname <> objname then
       update ge_t_partition_info set create_dead_line=str_cur_date where obj_name=curobjname;
       curobjname := objname;
       commit;
    end if;
 
    cur_date := start_date;
 
    if upper(ptype) = 'RANGE' then
      if upper(flg) = 'M' then
        while (cur_date <= end_date) loop
          par_name := pre_name || '_P' || to_char(cur_date, 'yyyyMM');
 
          str_cur_date := to_char(last_day(trunc(cur_date, 'DD')) + 1,'yyyy-MM-dd hh24:mi:ss');
          if upper(optype) = 'ADD' then
             select 'ALTER '||objtype||' '|| objname || ' ADD PARTITION ' || par_name ||
                   ' VALUES LESS THAN (TO_DATE(''' || str_cur_date ||
                   ''',''YYYY-MM-DD HH24:MI:SS'')) TABLESPACE ' || tbsname || ';'
              into str
              from dual;
          elsif upper(optype) = 'SPLIT' then
             select 'ALTER '||objtype||' '|| objname || ' SPLIT PARTITION ' || splitparname ||
                   ' AT (TO_DATE(''' || str_cur_date ||
                   ''',''YYYY-MM-DD HH24:MI:SS'')) INTO (PARTITION '||par_name||' TABLESPACE '||tbsname||',PARTITION '||splitparname||') ;'
              into str
              from dual;
          end if;
          dbms_output.put_line(str);
 
          if (cur_date <= end_date) then
            cur_date := add_months(cur_date, 1);
          end if;
        end loop;
      end if;
      if upper(flg) = 'D' then
        cur_date := cur_date + pdaynum;
        while (cur_date <= end_date) loop
          i            := i + 1;
          par_name     := pre_name || '_P' || to_char(cur_date, 'yyyyMM') || '_' || to_char(i);
          str_cur_date := to_char(cur_date, 'yyyy-MM-dd hh24:mi:ss');
          if upper(optype) = 'ADD' then
                select 'ALTER '||objtype||' '|| objname || ' ADD PARTITION '  || par_name ||
                       ' VALUES LESS THAN (TO_DATE(''' || str_cur_date ||
                       ''',''YYYY-MM-DD HH24:MI:SS'')) TABLESPACE ' || tbsname || ';'
                  into str
                  from dual;
          elsif upper(optype) = 'SPLIT' then
               select 'ALTER '||objtype||' '|| objname || ' SPLIT PARTITION ' || splitparname ||
                     ' AT (TO_DATE(''' || str_cur_date ||
                     ''',''YYYY-MM-DD HH24:MI:SS'')) INTO (PARTITION '||par_name||' TABLESPACE '||tbsname||',PARTITION '||splitparname||') ;'
                into str
                from dual;
          end if;
          dbms_output.put_line(str);
 
          if (to_char(cur_date, 'yyyyMM') <> to_char(cur_date + pdaynum, 'yyyyMM')) then
            i := 0;
          end if;
          if (cur_date < end_date and (cur_date + pdaynum) >= end_date) then
            cur_date := end_date;
          else
            cur_date := cur_date + pdaynum;
          end if;
        end loop;
 
      end if;
 
    end if;
 
    if upper(ptype) = 'HASH' then
      FOR j IN 1 .. pnumber LOOP
        select 'ALTER '||objtype||' '|| objname || ' ADD PARTITION ' || objname ||
               '_PHASH_' || j || ' TABLESPACE ' || tbsname || ';'
          into str
          from dual;
        dbms_output.put_line(str);
      end loop;
    end if;
  END LOOP;
 
end add_additional_partition2;

執行命令

?

set serveroutput on;
exec ADD_ADDITIONAL_PARTITION2;

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