數據庫每年都會新增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; |