oracle存儲過程,分區

create or replace procedure stp_maintenance_partition as
  v_currmax_date date;
  v_partdate     varchar2(20);
  v_high_value   varchar2(20);
  v_partname     varchar(30);

  v_tablename       varchar(80);
  v_tablespace_name varchar(80);
  v_partition_cnt   number(10);
  v_errormsg        varchar2(2000);
  v_tempname        varchar2(50);
  v_part_cnt        number(10);
  v_remote_part_cnt number(10);
  v_remote_tab_cnt  number(10);

  v_drop_date date;
  v_add_date  date;
begin
  --------處理按天分區的表--------------------------------------------------
  for r in (select distinct p.*
              from tm_tab_part_maintenance p, user_tab_partitions u
             where p.table_name = u.table_name
               and p.parition_type = 'DAY'
               and p.valid_flg = 1) loop
    v_tempname := r.table_name;

    v_currmax_date := null;
    v_drop_date    := sysdate - r.drop_time_units - 1;

    for cur_part in (select partition_name, high_value
                       from user_tab_partitions
                      where table_name = r.table_name
                      order by partition_name) loop
      v_high_value := substr(cur_part.high_value, 11, 19);
      --刪除超過時間的分區
      if to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS') <= v_drop_date then

        --判斷是否這個表只剩一個分區
        select count(*)
          into v_part_cnt
          from user_tab_partitions
         where table_name = r.table_name;

        if (v_part_cnt > 1) then
          execute immediate 'alter table ' || r.table_name ||
                            ' drop partition ' || cur_part.partition_name ||
                            ' /*ggh_notsync*/';
        end if;
      end if;

      --找出該分區表目前最大的high_value
      if v_currmax_date is null then
        v_currmax_date := to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS');
      elsif to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS') > v_currmax_date then
        v_currmax_date := to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS');
      end if;
    end loop;

    --如果配置表裏表空間爲空,找出該表目前所用表空間
    if r.TABLESPACE_NAME is null then
      select tablespace_name
        into v_tablespace_name
        from user_tab_partitions
       where table_name = r.table_name
         and rownum = 1;
    else
      v_tablespace_name := r.TABLESPACE_NAME;
    end if;

    ----增加分區
    while (v_currmax_date - trunc(sysdate) <= r.add_time_units) loop

      v_partname     := to_char(trunc(v_currmax_date), 'YYYYMMDD');
      v_partdate     := to_char(trunc(v_currmax_date + 1),
                                'YYYY-MM-DD HH24:MI:SS');
      v_currmax_date := v_currmax_date + 1;

      select count(1)
        into v_partition_cnt
        from user_tab_partitions
       where table_name = r.table_name
         and partition_name = r.partition_pre || v_partname;

      if (v_partition_cnt = 0) then
        execute immediate 'alter table ' || r.table_name ||
                          ' add partition ' || r.partition_pre ||
                          v_partname || ' values less than (to_date(''' ||
                          v_partdate ||
                          ''',''YYYY-MM-DD HH24:MI:SS'')) tablespace ' ||
                          v_tablespace_name;

        --如果配置了索引表空間索引,索引分區需rebuild到指定的索引表空間
        if (r.index_tb_name is not null) then
          for cur_part_ind in (select a.index_name,
                                      a.partition_name,
                                      a.tablespace_name,
                                      a.status
                                 from user_ind_partitions a, user_indexes b
                                where a.index_name = b.index_name
                                  and b.table_name = r.table_name
                                  and a.partition_name =
                                      r.partition_pre || v_partname) loop
            execute immediate 'alter index ' || cur_part_ind.index_name ||
                              ' rebuild partition ' ||
                              cur_part_ind.partition_name || ' tablespace ' ||
                              r.index_tb_name;
          end loop;
        end if;

      end if;

    end loop;

    --重建不可用的全局索引
    for cur_global_ind in (select index_name, tablespace_name, status
                             from user_indexes
                            where table_name = r.table_name
                              and status = 'UNUSABLE') loop
      execute immediate 'alter index ' || cur_global_ind.index_name ||
                        ' rebuild tablespace ' ||
                        cur_global_ind.tablespace_name;
    end loop;

    --重建不可用的局部索引
    for cur_part_ind in (select a.index_name,
                                a.partition_name,
                                a.tablespace_name,
                                a.status
                           from user_ind_partitions a, user_indexes b
                          where a.index_name = b.index_name
                            and b.table_name = r.table_name
                            and a.status = 'UNUSABLE') loop
      execute immediate 'alter index ' || cur_part_ind.index_name ||
                        ' rebuild partition ' ||
                        cur_part_ind.partition_name || ' tablespace ' ||
                        cur_part_ind.tablespace_name;
    end loop;
  end loop;

  --------處理按月分區的表-----------------------------------------------
  for rm in (select distinct p.*
               from tm_tab_part_maintenance p, user_tab_partitions u
              where p.table_name = u.table_name
                and p.parition_type = 'MONTH'
                and p.valid_flg = 1) loop

    v_tempname := rm.table_name;

    v_currmax_date := null;
    v_drop_date    := add_months(trunc(sysdate, 'MM'), -rm.drop_time_units);

    for cur_part in (select partition_name, high_value
                       from user_tab_partitions
                      where table_name = rm.table_name
                      order by partition_name) loop

      v_high_value := substr(cur_part.high_value, 11, 19);
      --刪除超過時間的分區
      if to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS') <= v_drop_date then

        --判斷是否這個表只剩一個分區
        select count(*)
          into v_part_cnt
          from user_tab_partitions
         where table_name = rm.table_name;

        if (v_part_cnt > 1) then
          execute immediate 'alter table ' || rm.table_name ||
                            ' drop partition ' || cur_part.partition_name ||
                            ' /*ggh_notsync*/';
        end if;
      end if;

      --找出該分區表目前最大的high_value
      if v_currmax_date is null then
        v_currmax_date := to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS');
      elsif to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS') > v_currmax_date then
        v_currmax_date := to_date(v_high_value, 'YYYY-MM-DD HH24:MI:SS');
      end if;
    end loop;

    --如果配置表裏表空間爲空,找出該表目前所用表空間
    if rm.tablespace_name is null then
      select tablespace_name
        into v_tablespace_name
        from user_tab_partitions
       where table_name = rm.table_name
         and rownum = 1;
    else
      v_tablespace_name := rm.TABLESPACE_NAME;
    end if;

    --增加分區
    while (add_months(v_currmax_date, -rm.add_time_units) <=
          trunc(sysdate, 'MM')) loop

      v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM');
      v_partdate     := to_char(trunc(add_months(v_currmax_date, 1)),
                                'YYYY-MM-DD HH24:MI:SS');
      v_currmax_date := add_months(v_currmax_date, 1);

      select count(1)
        into v_partition_cnt
        from user_tab_partitions
       where table_name = rm.table_name
         and partition_name = rm.partition_pre || v_partname;

      if (v_partition_cnt = 0) then
        execute immediate 'alter table ' || rm.table_name ||
                          ' add partition ' || rm.partition_pre ||
                          v_partname || ' values less than (to_date(''' ||
                          v_partdate ||
                          ''',''YYYY-MM-DD HH24:MI:SS'')) tablespace ' ||
                          v_tablespace_name;

        --如果配置了索引表空間索引,索引分區需rebuild到指定的索引表空間
        if (rm.index_tb_name is not null) then
          for cur_part_ind in (select a.index_name,
                                      a.partition_name,
                                      a.tablespace_name,
                                      a.status
                                 from user_ind_partitions a, user_indexes b
                                where a.index_name = b.index_name
                                  and b.table_name = rm.table_name
                                  and a.partition_name =
                                      rm.partition_pre || v_partname) loop
            execute immediate 'alter index ' || cur_part_ind.index_name ||
                              ' rebuild partition ' ||
                              cur_part_ind.partition_name || ' tablespace ' ||
                              rm.index_tb_name;
          end loop;
        end if;

      end if;
    end loop;

    --重建不可用的全局索引
    for cur_global_ind in (select index_name, tablespace_name, status
                             from user_indexes
                            where table_name = rm.table_name
                              and status = 'UNUSABLE') loop
      execute immediate 'alter index ' || cur_global_ind.index_name ||
                        ' rebuild tablespace ' ||
                        cur_global_ind.tablespace_name;
    end loop;

    --重建不可用的局部索引
    for cur_part_ind in (select a.index_name,
                                a.partition_name,
                                a.tablespace_name,
                                a.status
                           from user_ind_partitions a, user_indexes b
                          where a.index_name = b.index_name
                            and b.table_name = rm.table_name
                            and a.status = 'UNUSABLE') loop
      execute immediate 'alter index ' || cur_part_ind.index_name ||
                        ' rebuild partition ' ||
                        cur_part_ind.partition_name || ' tablespace ' ||
                        cur_part_ind.tablespace_name;
    end loop;
  end loop;

exception
  when others then
    /*dbms_output.put_line('Error:' || sqlcode || ':' || sqlerrm);
    v_errormsg := 'Error:' || sqlcode || ':' || sqlerrm || ';' || CHR(10) ||
                  v_tempname || ' add partition failed!';*/

    /* tivoli.SEND_MAIL(vIn_Sender       => '[email protected]',
    vIn_ReceiverList => '[email protected]',
    vIn_Subject      => 'add partition failed',
    vIn_Text         => v_errormsg);*/
    /*utl_mail.send(sender     => '[email protected]',
    recipients => '[email protected]',
    subject    => 'add partition failed!',
    message    => 'sfods add partition failed,please check it',
    mime_type  => 'text/plain;charset=ZHS16GBK');*/

    PKG_SYS_LOG.ERROR_LOG(P_PACKAGE_NAME => '',
                          P_PROC_NAME    => 'STP_MAINTENANCE_PARTITION',
                          P_EXCEP_DT     => SYSDATE,
                          P_EXCEP_CODE   => SQLCODE,
                          P_EXCEP_DESC   => SQLERRM,
                          P_EXCEP_REMK   => '增加/刪除分區 ' || v_tempname,
                          P_LINE_NO      => null);
end stp_maintenance_partition;

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