oracle 表分区

分区表
通过本章节的学习,您可以学到以下几个问题
1、 了解分区表的概念
2、 清楚分区表的用途
3、 了解分区表的分类
4、 了解分区表的操作
 
在我们使用普通表的过程中会有数据量特别大的表,当一个表的数据超过过2000万条或占用2G空间时,建议建立分区表
 
分区表的分类:
Range(范围)分区
Hash(哈希)分区
List(列表)分区
以及组合分区:Range-Hash,Range-List
 
分区的优点:
 
增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;
改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
 
执行概要
分区功能可以提高许多应用程序的可管理性、性能与可用性。通过分区功能,可以将表、索引和索引组织表进一步细分为段,从而能够更精确地管理和访问这些数据库对象。Orac#提供了种类繁多的分区方案以满足每种业务要求。而且,因为sql语句中分区是完全透明的,所以该功能几乎可应用于任何应用程序。
 
分区功能的优势
分区功能通过改善可管理性、性能和可用性,从而为各式应用程序带来了极大的好处。通常,分区可以使某些查询以及维护操作的性能大大提高。此外,分区还可以极大简化常见的管理任务。通过分区,数据库设计人员和管理员能够解决前沿应用程序带来的一些难题。分区是构建千兆字节数据系统或超高可用性系统的关键工具。
 
分区功能的基本知识
分区功能能够将表、索引或索引组织表进一步细分为段。这些数据库对象的段叫做分区。每个分区有自己的名称,还可以选择自己的存储特性。
从数据库管理员的角度来看,一个分区后的对象具有多个段,这些段既可进行集体管理,也可单独管理。这就使数据库管理员在管理分区后的对象时有相当大的灵活性。但是,从应用程序的角度来看,分区后的表与非分区表完全相同,使#S#D#命令访问分区后的表时,无需任何修改,表的分区是通过“分区键”来实现的,分区键指的是一些列,这些列决定了某一行所在的分区。Orac#数据#1#提供了六项技术用于对表进行分区:
#范围分区
每个分区都由一个分区键值范围指定(对于一个以日期列作为分区键的表,“2005年1月”分区包含分区键值为从“2005年1月1日”到“2005年1月31日”的行)。
 
范围分区表示例:
 
假设有一个企业的销售数据比较大,可以作一个范围分区表
 
创建四个表空间,为分区表所用,应该把分区放在不同的物理设备上,性能更好,可我的测试环境是同一个物理设备

  1 select * from USER_TABLESPACES;
  2 select * from DBA_TABLESPACE_GROUPS;
  3 select * from dba_users;
  4 select tablespace_name,file_id,file_name,autoextensible,
  5 round(bytes/1024/1024/1024,3) "used(G)",round(maxbytes/1024/1024/1024,3) "size(G)" 
  6 from dba_data_files order by tablespace_name;
  7 
  8 create tablespace lxl_test1 datafile '/dba/user_oracle/bspdev1/bspdev1/lxl_test1.dbf' size 50M;
  9 CREATE TABLESPACE LXL_TEST2 DATAFILE '/dba/user_oracle/bspdev1/bspdev1/lxl_test2.dbf' size 50M;
 10 CREATE TABLESPACE LXL_TEST3 DATAFILE '/dba/user_oracle/bspdev1/bspdev1/lxl_test3.dbf' size 50M;
 11 CREATE TABLESPACE LXL_TEST4 DATAFILE '/dba/user_oracle/bspdev1/bspdev1/lxl_test4.dbf' size 50M;
 12 --范围分区
 13 create table tt_lxl_part_test1(
 14        id number ,
 15        name varchar2(20),
 16        total_cnt number,
 17        price number,
 18        create_tm date not null
 19 )partition by range(create_tm)
 20 (partition lxl_part1 values less than (to_date('2016-09-18','YYYY-MM-DD')) tablespace lxl_test1,
 21 partition lxl_part2 values less than (to_date('2016-10-18','YYYY-MM-DD'))tablespace lxl_test2,
 22 partition lxl_part3 values less than (to_date('2016-11-18','YYYY-MM-DD'))tablespace lxl_test3,
 23 partition lxl_part4 values less than (to_date('2016-12-18','YYYY-MM-DD'))tablespace lxl_test4
 24 );
 25 insert into tt_lxl_part_test1 values(1,'蔬菜','10','2.9',to_date('2016-09-10','YYYY-MM-DD'));
 26 insert into tt_lxl_part_test1 values(2,'水果','13','7.9',to_date('2016-10-10','YYYY-MM-DD'));
 27 insert into tt_lxl_part_test1 values(3,'零食','16','5.9',to_date('2016-11-10','YYYY-MM-DD'));
 28 insert into tt_lxl_part_test1 values(4,'大米','17','11',to_date('2016-12-10','YYYY-MM-DD'));
 29 
 30 select * from tt_lxl_part_test1 partition(lxl_part1);
 31 select * from tt_lxl_part_test1 partition(lxl_part2);
 32 select * from tt_lxl_part_test1 partition(lxl_part3);
 33 select * from tt_lxl_part_test1 partition(lxl_part4);
 34 --列表分区
 35 create table lxl_part_test2(
 36 id number(4),
 37 name varchar2(30),
 38 loca varchar2(30)
 39 )partition by list(loca)
 40 (
 41    partition p1 values('北京') tablespace lxl_test1,
 42    partition p2 values('上海','天津','重庆') tablespace lxl_test2,
 43    partition p3 values('广东','福建') tablespace lxl_test3,
 44    partition p4 values(default) tablespace lxl_test4
 45 );
 46 insert into lxl_part_test2 values(1,'李小龙','佛山');
 47 insert into lxl_part_test2 values(2,'顺丰','北京');
 48 insert into lxl_part_test2 values(3,'速运','上海');
 49 insert into lxl_part_test2 values(4,'系统集成','天津');
 50 insert into lxl_part_test2 values(5,'数据研发中心','重庆');
 51 insert into lxl_part_test2 values(6,'深圳','广东');
 52 insert into lxl_part_test2 values(7,'南山','福建');
 53 select * from lxl_part_test2 partition(p1);
 54 select * from lxl_part_test2 partition(p2);
 55 select * from lxl_part_test2 partition(p3);
 56 select * from lxl_part_test2 partition(p4);
 57 --散列分区
 58 create table lxl_part_test3(
 59       id number primary key,
 60       class_id number(8) not null,
 61       name varchar2(300),
 62       finished_date date
 63 )
 64 partition by hash(id)
 65 (
 66     partition p01 tablespace lxl_test1,
 67     partition p02 tablespace lxl_test2,
 68     partition p03 tablespace lxl_test3
 69 );
 70 insert into lxl_part_test3 values
 71 (3,12, '上等的虎皮',to_date('2009-05-30','yyyy-mm-dd'));
 72 insert into lxl_part_test3 values
 73 (1,13, '虎皮',to_date('2009-05-30','yyyy-mm-dd'));
 74 insert into lxl_part_test3 values
 75 (200,15, '中等的虎皮',to_date('2009-05-30','yyyy-mm-dd'));
 76 insert into lxl_part_test3 values
 77 (230,19, '猫虎皮',to_date('2009-05-30','yyyy-mm-dd'));
 78 
 79 select * from lxl_part_test3 partition(p01);
 80 select * from lxl_part_test3 partition(p02);
 81 select * from lxl_part_test3 partition(p03);
 82 
 83 --组合分区  散列+范围
 84 create table lxl_part_test4(
 85        id number,
 86        name varchar2(30),
 87        finish_date date
 88 )partition by range(finish_date)
 89 subpartition by hash(id)
 90 subpartitions 2
 91 (
 92     partition p_group1 values less than(to_date('2016-09-18','YYYY-MM-DD')) TABLESPACE lxl_test1,
 93     partition p_group2 values less than (to_date('2016-10-18','YYYY-MM-DD')) tablespace lxl_test2,
 94     partition p_group3 values less than(maxvalue) tablespace lxl_test3
 95 );
 96  insert into lxl_part_test4 values
 97 (1,'所发生的',to_date('20161003','yyyymmdd'));
 98  
 99  insert into lxl_part_test4 values
100 (2,'分区表测试',to_date('20161014','yyyymmdd'));
101  
102  insert into lxl_part_test4 values
103 (3,'分区表规划',to_date('20161020','yyyymmdd'));
104  
105  insert into lxl_part_test4 values
106 (4,'stream实施',to_date('20161018','yyyymmdd'));
107  
108 insert into lxl_part_test4 values
109 (5,'oracle设计',to_date('20161103','yyyymmdd'));
110  
111  insert into lxl_part_test4 values
112 (6,'数据库规划',to_date('20161103','yyyymmdd'));
113 
114 select * from lxl_part_test4 partition(p_group3);
115 select * from lxl_part_test4 partition(p_group2);
116 select * from lxl_part_test4 partition(p_group1);
117 
118 --组合分区  列表+范围
119 create  table lxl_part_test5(
120 id NUMBER(6),
121 name VARCHAR2(20),
122 area VARCHAR2(30),
123 create_tm date
124 )partition by range(create_tm)
125 subpartition by list(area)
126 subpartition template(
127 subpartition east values('CHINA', 'JAPAN', 'INDIA', 'THAILAND'),
128 subpartition west values('AMERICA', 'GERMANY', 'ITALY', 'SWITZERLAND'),
129 subpartition other values(default))
130 (
131 partition p_group04 values less than(to_date('2016-09-18','YYYY-MM-DD')),
132 partition p_group05 values less than(to_date('2016-10-18','YYYY-MM-DD')),
133 partition p_group06 values less than(MAXVALUE)
134 );
135  
136 
137 insert into lxl_part_test5 values (1,'阿斯顿发送到','china',to_date('2016-09-08','YYYY-MM-DD'));
138  
139 insert into lxl_part_test5 values (2,'多福多寿','GERMANY',to_date('2016-09-17','YYYY-MM-DD'));
140 insert into lxl_part_test5 values (75,'oracle','JAPAN',to_date('2016-09-18','YYYY-MM-DD'));
141 insert into lxl_part_test5 values (34,'IBM','SWITZERLAND',to_date('2016-09-19','YYYY-MM-DD'));
142 insert into lxl_part_test5 values (43,'SUN','CHINA',to_date('2016-10-18','YYYY-MM-DD'));
143 insert into lxl_part_test5 values (876,'DELL','AMERICA',to_date('2017-09-18','YYYY-MM-DD'));
144 insert into lxl_part_test5 values (866,'SYSBASE','INDIA',to_date('2016-09-28','YYYY-MM-DD'));
145 
146 select * from lxl_part_test5 partition(p_group04 );
View Code

 #索引组织表可以按范围、列表或散列进行分区。
Oracle 数据库10g还提供了三种类型的分区索引:
 
#本地索引
本地索引是其分区方式与其所在基础表的分区方式一模一样的索引。本地索引的每个分区仅对应于其所在基础表的一个分区。
 
示例:
SQL> CREATE INDEX idx_dyx_part_test1 ON dyx_part_test1 (xiaos_date) LOCAL
  2  (PARTITION idx_dyx_part_test1_01 TABLESPACE ts_xiaos2009q1,
  3  PARTITION idx_dyx_part_test1_02 TABLESPACE ts_xiaos2009q2,
  4  PARTITION idx_dyx_part_test1_03 TABLESPACE ts_xiaos2009q3,
  5  PARTITION idx_dyx_part_test1_04 TABLESPACE ts_xiaos2009q4
  6  ) TABLESPACE users;
 
Index created.
 
#全局分区索引
分区索引是使用不同于其所在表的分区键进行分区的索引,其所在表可以是分区表或非分区表。全局分区的索引可以使用
范围或散列分区进行分区。例如,某个表可以按月份进行范围分区,因此具有十二个分区,而该表上的索引则可以使用不同的分区键
进行范围分区,从而具有不同的分区数量。
 
分区索引就是在所有每个区上单独创建索引,它能自动维护,在drop或truncate某个分区时不影响该索引的其他分区索引的使用,也就是索
引不会失效,维护起来比较方便,但是在查询性能稍微有点影响
 
#全局非分区索引
全局非分区索引基本上和非分区表的索引一样。索引结构是不分区的。
Oracle 提供了一系列丰富的技术,可用于对表、索引和索引组织表进行分区,因此可以针对任何业务环境中的任何应用程序进行最佳的分区。
Oracle 还提供一套完整的SQL命令,用于管理分区表。其中包括添加新分区、删除分区、分拆分区以及合并分区的命令。
 
用分区功能提高可管理性
    通过 Oracle 分区功能,可将表和索引分成更多、更小的可管理单元,从而使数据库管理员能以“化整为零,个个击破”的方式管理数据。
使用分区功能,维护操作可集中于表的特定部分。
例如,数据库管理员可以只对表的一部分做备份,而不必对整个表做备份。对整个数据库对象的维护操作,可以在每个分区的基础上进行,
从而将维护工作分解成更容易管理的小块。
 
    利用分区功能提高可管理性的一个典型用法是支持数据仓库中的‘滚动视窗’加载进程。假设数据库管理员每周向表中加载新数据。可以对
该表进行范围分区,使每个分区包含一周的数据。这样加载进程只是简单地添加新的分区。添加一个分区的操作比修改整个表效率高很多,因
为 DBA 不需要修改任何其他分区。
 
用分区功能提高性能
由于限制了所检查或操作的数据数量,同时支持并行任务执行,Oracle 分区功能实现了性能上增益。这些特性包括:
 
#分区修整
分区修整是用分区功能提高性能的最简单最有价值的手段。分区修整常常能够将查询性能提高几个数量级。例如,假设某个应用程序包含一个存
储订单历史记录的 Orders 表,并且此表已按周分区。查询一周的订单只需访问该订单表的一个分区。如果该订单表包含两年的历史记录,这个
查询只需要访问一个分区而不是一百零四个。该查询的执行速度因为分区修整而有可能快一百倍。分区修整能与所有其他 Oracle 性能特性协作。
Oracle 能将分区修整功能与任何索引技术、联接技术或并行访问方法结合使用。
 
 
分区表的维护:
增加分区:
 
 
SQL> ALTER TABLE dyx_part_test1 ADD PARTITION xiaoss2009_q5
  2  VALUES LESS THAN (TO_DATE('2010-06-01','YYYY-MM-DD'))
  3  TABLESPACE users;
 
Table altered.
 
如果已有maxvalue分区,不能增加分区,可以采取分裂分区的办法增加分区!
 
删除分区:
 
 
SQL> ALTER TABLE dyx_part_test1 DROP partition xiaoss2009_q5;
 
Table altered.
 
截短分区:
 
SQL> alter table dyx_part_test1 truncate partition xiaoss2009_q4;
 
Table truncated.
 
合并分区:
 
SQL> alter table dyx_part_test1 merge partitions xiaoss2009_q3,xiaoss2009_q4 into partition xiaoss2009_q4;
 
Table altered.
 
SQL> alter index idx_dyx_part_test1 rebuild partition idx_dyx_part_test1_01 parallel 4;
 
Index altered.
 
分裂分区:
 
范围示例:
SQL> ALTER TABLE dyx_part_test1
  2  SPLIT PARTITION xiaoss2009_q4
  3  AT (TO_DATE('2009-10-01','YYYY-MM-DD'))
  4  INTO (partition xiaoss2009_q3,partition xiaoss2009_q4);
 
Table altered.
 
列表示例:
 
SQL> select * from dyx_part_test2 partition(p2);
 
        ID NAME                           LOCA
---------- ------------------------------ ------------------------------
         3 广成子                         天津
         5 太已真人                       上海
         7 元始天尊                       重庆
 
SQL> alter table dyx_part_test2 split partition p2 values ('天津','重庆') into (partition p5,partition p6);
 
Table altered.
 
SQL> select * from dyx_part_test2 partition(p2);
select * from dyx_part_test2 partition(p2)
                                       *
ERROR at line 1:
ORA-02149: Specified partition does not exist
 
SQL> select * from dyx_part_test2 partition(p5);
 
        ID NAME                           LOCA
---------- ------------------------------ ------------------------------
         3 广成子                         天津
         7 元始天尊                       重庆
 
SQL> select * from dyx_part_test2 partition(p6);
 
        ID NAME                           LOCA
---------- ------------------------------ ------------------------------
         5 太已真人                       上海
 
注:分开的分区(上例中的p5和p6)不能是原分区表中已经有的不同于被分区的分区
 
交换分区:
    交换分区(Exchange partition)提供了一种方式,让你在表与表或分区与分区之间迁移数据,注意不是将表转换成分区或非分区的形式,而仅只是迁移表中数据
(互相迁移),由于其号称是采用了更改数据字典的方式,因此效率最高(几乎不涉及io操作)。Exchange partition适用于所有分区格式,你可以将数据从分区表迁移
到非分区表,也可以从非分区表迁移至分区表,或者从hash partition到range partition诸如此类吧
 
SQL> create table dyx_part_test7 (id number,name varchar2(50))
  2  partition by range(id)
  3  (partition t_range_p1 values less than (10) tablespace ts_xiaos2009q1,
  4  partition t_range_p2 values less than (20) tablespace ts_xiaos2009q2,
  5  partition t_range_p3 values less than (30) tablespace ts_xiaos2009q3,
  6  partition t_range_pmax values less than (maxvalue) tablespace ts_xiaos2009q4
  7  );
 
Table created.
 
SQL> insert into dyx_part_test7 values (11,'a');
 
1 row created.
 
SQL> insert into dyx_part_test7 values (12,'b');
 
1 row created.
 
SQL> insert into dyx_part_test7 values (13,'c');
 
1 row created.
 
SQL> commit;
 
Commit complete.
 
SQL> create table dyx_part_test7_tmp (id number,name varchar2(50));
 
Table created.
 
SQL> alter table dyx_part_test7 exchange partition t_range_p2
  2  with table dyx_part_test7_tmp;
 
Table altered.
 
SQL> select * from dyx_part_test7 partition(t_range_p2);
 
no rows selected
 
SQL> select * from dyx_part_test7_tmp;
 
        ID NAME
---------- --------------------------------------------------
        11 a
        12 b
        13 c
记录成功交换到未分区的表中
 
接着再执行一次交换
 
SQL> alter table dyx_part_test7 exchange partition t_range_p2
  2  with table dyx_part_test7_tmp;
 
Table altered.
 
SQL> select * from dyx_part_test7_tmp;
 
no rows selected
 
SQL> select * from dyx_part_test7 partition(t_range_p2);
 
        ID NAME
---------- --------------------------------------------------
        11 a
        12 b
        13 c
从上面可以看出又交换回去了
 
SQL> insert into dyx_part_test7_tmp values (15,'d');
 
1 row created.
 
SQL> insert into dyx_part_test7_tmp values (16,'e');
 
1 row created.
 
SQL> insert into dyx_part_test7_tmp values (17,'d');
 
1 row created.
 
SQL>
SQL> commit;
 
Commit complete.
 
SQL> alter table dyx_part_test7 exchange partition t_range_p2
  2  with table dyx_part_test7_tmp;
 
Table altered.
 
SQL>
SQL> select *from dyx_part_test7 partition(t_range_p2);
 
        ID NAME
---------- --------------------------------------------------
        15 d
        16 e
        17 d
 
SQL> select *from dyx_part_test7_tmp;
 
        ID NAME
---------- --------------------------------------------------
        11 a
        12 b
        13 c
从上面的测试可以看出,两个表或分区表是在交换数据!
 
注意:
  参于交换的两表之间表结构必须一致,除非附加with validation子句;
  如果是从非分区表向分区表做交换,非分区表中的数据必须符合分区表中指定分区的规则,除非附加without validation子句;
  如果从分区表向分区表做交换,被交换的分区的数据必须符合分区规则,除非附加without validation子句;
  Global索引或涉及到数据改动了的global索引分区会被置为unusable,除非附加update indexes子句。
  提示:
  一旦附加了without validation子句,则表示不再验证数据有效性,因此指定该子句时务必慎重。
 
访问指定分区:
 
SQL> select * from dyx_part_test2 partition(p1);
 
        ID NAME                           LOCA
---------- ------------------------------ ------------------------------
         2 云中子                         北京
         8 南级战神                       北京
 
导出导入:
 
EXPORT指定分区:
 
[oracle@ora ~]$ exp dyx/dyx tables=dyx_part_test2:p1 file=dyx_part_test2_p1.dmp
 
Export: Release 10.2.0.1.0 - Production on Sat Apr 25 09:42:47 2009
 
Copyright (c) 1982, 2005, Oracle.  All rights reserved.
 
 
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
Export done in ZHS16GBK character set and AL16UTF16 NCHAR character set
 
About to export specified tables via Conventional Path ...
. . exporting table                 DYX_PART_TEST2
. . exporting partition                             P1          2 rows exported
EXP-00091: Exporting questionable statistics.
Export terminated successfully with warnings.
 
IMPORT指定分区:
 
[oracle@ora ~]$ imp dyx/dyx file=dyx_part_test2_p1.dmp TABLES=(dyx_part_test2:p1) IGNORE=y
 
Import: Release 10.2.0.1.0 - Production on Sat Apr 25 09:44:15 2009
 
Copyright (c) 1982, 2005, Oracle.  All rights reserved.
 
 
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
 
Export file created by EXPORT:V10.02.01 via conventional path
import done in ZHS16GBK character set and AL16UTF16 NCHAR character set
. importing DYX's objects into DYX
. importing DYX's objects into DYX
. . importing partition          "DYX_PART_TEST2":"P1"          2 rows imported
Import terminated successfully without warnings.
 
 
普通表变为分区表
 
将已存在数据的普通表转变为分区表,没有办法通过修改属性的方式直接转化为分区表,必须通过重建的方式进行转变,一般可以有三种方法:
 
方法一:利用原表重建分区表。
 
SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY,TIME DATE);
Table created.
 
SQL> INSERT INTO T
  2  SELECT ROWNUM, SYSDATE - ROWNUM FROM user_OBJECTS WHERE ROWNUM <= 5000;
57 rows created.
 
SQL> commit;
Commit complete.
 
SQL> CREATE TABLE T_NEW (ID, TIME) PARTITION BY RANGE (TIME)
  2  (PARTITION P1 VALUES LESS THAN (TO_DATE('2009-01-01', 'YYYY-MM-DD')),
  3  PARTITION P2 VALUES LESS THAN (TO_DATE('2009-04-01', 'YYYY-MM-DD')),
  4  PARTITION P3 VALUES LESS THAN (TO_DATE('2009-10-01', 'YYYY-MM-DD')),
  5  PARTITION P4 VALUES LESS THAN (MAXVALUE))
  6  AS SELECT ID,TIME FROM T;
 
Table created.
 
更换表名
SQL> RENAME T TO T_OLD;
Table renamed.
 
SQL> SQL> RENAME T_NEW TO T;
Table renamed.
 
SQL> SELECT COUNT(*) FROM T PARTITION (P2);   
 
  COUNT(*)
----------
        33
 
SQL> SELECT COUNT(*) FROM T PARTITION (P3);
 
  COUNT(*)
----------
        24
 
优点:方法简单易用,由于采用DDL语句,不会产生UNDO,且只产生少量REDO,效率相对较高,而且建表完成后数据已经在分布到各个分区中了。
 
不足:对于数据的一致性方面还需要额外的考虑。由于几乎没有办法通过手工锁定T表的方式保证一致性,在执行CREATE TABLE语句和RENAME T_NEW TO T语句直接的
修改可能会丢失,如果要保证一致性,需要在执行完语句后对数据进行检查,而这个代价是比较大的。另外在执行两个RENAME语句之间执行的对T的访问会失败。
适用于修改不频繁的表,在闲时进行操作,表的数据量不宜太大。
 
 
方法二:使用交换分区的方法。
因前面有闪换分区的示例,这里就不用重新示例了
 
优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行
完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。
 
不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行
分区的SPLIT操作,会增加操作的复杂度,效率也会降低。
 
适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。
 
 
方法三:Oracle9i以上版本,利用在线重定义功能
 
不作示例
 
优点:保证数据的一致性,在大部分时间内,表T都可以正常进行DML操作。只在切换的瞬间锁表,具有很高的可用性。这种方法具有很强的灵活性,对各种不同的需
要都能满足。而且,可以在切换前进行相应的授权并建立各种约束,可以做到切换完成后不再需要任何额外的管理操作。
 
相关视图:
 
显示当前用户可访问的所有分区表信息﹕ALL_PART_TABLES
 
显示当前用户所有分区表的信息﹕USER_PART_TABLES
 
显示表分区信息 显示数据库所有分区表的详细分区信息﹕DBA_TAB_PARTITIONS
 
显示当前用户可访问的所有分区表的详细分区信息﹕ALL_TAB_PARTITIONS
 
 
显示当前用户所有分区表的详细分区信息﹕USER_TAB_PARTITIONS
 
显示子分区信息 显示数据库所有组合分区表的子分区信息﹕DBA_TAB_SUBPARTITIONS
 
显示当前用户可访问的所有组合分区表的子分区信息﹕ALL_TAB_SUBPARTITIONS
 
 
显示当前用户所有组合分区表的子分区信息﹕USER_TAB_SUBPARTITIONS
 
 
显示分区列 显示数据库所有分区表的分区列信息﹕DBA_PART_KEY_COLUMNS
 
显示当前用户可访问的所有分区表的分区列信息﹕ALL_PART_KEY_COLUMNS
 
 
显示当前用户所有分区表的分区列信息﹕USER_PART_KEY_COLUMNS
 
显示子分区列 显示数据库所有分区表的子分区列信息﹕DBA_SUBPART_KEY_COLUMNS
 
显示当前用户可访问的所有分区表的子分区列信息﹕ALL_SUBPART_KEY_COLUMNS
 
显示当前用户所有分区表的子分区列信息﹕USER_SUBPART_KEY_COLUMNS

 

1.创建用户
create user DBAMON identified by "bspdev"
default tablespace BSP_DATA
temporary tablespace temp profile DEFAULT;
2.授权
grant connect to DBAMON;
grant create indextype to DBAMON;
grant create job to DBAMON;
grant create materialized view to DBAMON;
grant create procedure to DBAMON;
grant create public synonym to DBAMON;
grant create sequence to DBAMON;
grant create session to DBAMON;
grant create table to DBAMON;
grant create trigger to DBAMON;
grant create type to DBAMON;
grant create view to DBAMON;
grant unlimited tablespace to DBAMON;
alter user DBAMON quota unlimited on BSP_DATA;

grant connect,resource,dba to DBAMON

grant sys to DBAMON;
grant all on sys to DBAMON;


grant select on sys.dba_part_tables to DBAMON;
grant select on sys.dba_part_tables to bspdev;
grant select on sys.dba_tab_partitions to DBAMON;
grant select on sys.dba_tab_partitions to bspdev;
grant select on sys.dba_indexes to DBAMON;
grant select on sys.dba_indexes to bspdev;
grant select on sys.dba_ind_partitions to DBAMON;
grant select on sys.dba_ind_partitions to bspdev;
grant select on sys.DBA_TAB_COLUMNS to DBAMON;
grant select on sys.DBA_TAB_COLUMNS to bspdev;
grant select on sys.DBA_PART_KEY_COLUMNS to DBAMON;
grant select on sys.DBA_PART_KEY_COLUMNS to bspdev;

grant select on sys.v$instance to DBAMON;
grant select on v$instance to bspdev;
v$instance

select instance_name from sys.v_$instance;



alter user sys account unlock;

 select * /*into v_count*/ from v$instance where version like '11%';
 

DECLARE
       V_MSG VARCHAR(4000);
BEGIN 
      DBAMON.CONFIG_TAB_POLICY( v_MSG => V_MSG,
                                v_table_owner => 'BSPDEV',
                                v_table_name => 'TT_GEN_SPE_ROUTE_RECORD_BAK',
                                v_drop_time_units => 3,
                                v_policy => 4,
                                v_partition_type => 'MONTH' );
      DBMS_OUTPUT.put_line(SUBSTR(V_MSG,1,1000));
      COMMIT;
  END;
/
 
 select * from dba_part_tables t where t.table_name='TT_GEN_SPE_ROUTE_RECORD_BAK';
 select * from tbl_part_info t where t.table_name='TT_GEN_SPE_ROUTE_RECORD_BAK';



create table DBAMON.TBL_PART_INFO
(
  table_owner           VARCHAR2(40),
  table_name            VARCHAR2(60),
  min_partition         VARCHAR2(60),
  max_partition         VARCHAR2(60),
  min_date              VARCHAR2(15),
  max_date              VARCHAR2(15),
  min_value             VARCHAR2(2000),
  max_value             VARCHAR2(2000),
  partition_column_type VARCHAR2(20),
  sample_time           DATE,
  existmax              VARCHAR2(10),
  format                VARCHAR2(15),
  partition_type        VARCHAR2(10),
  global_indx           NUMBER(10),
  part_column_name      VARCHAR2(100),
  autointerval          VARCHAR2(100)
);

create table DBAMON.TBL_TAB_PART_CONFIG
(
  id                    NUMBER(10) not null,
  table_owner           VARCHAR2(30) not null,
  table_name            VARCHAR2(30) not null,
  partition_column_type VARCHAR2(26) not null,
  partition_pre         VARCHAR2(26) default 'P' not null,
  partition_type        VARCHAR2(30) not null,
  drop_time_units       NUMBER(10) not null,
  add_time_units        NUMBER(10) not null,
  tablespace_name       VARCHAR2(30),
  index_tb_name         VARCHAR2(30),
  valid_flg             NUMBER(1) not null,
  config_type           VARCHAR2(100),
  format                VARCHAR2(15),
  shour                 NUMBER(2),
  ehour                 NUMBER(2)
);
-- Add comments to the columns 
comment on column DBAMON.TBL_TAB_PART_CONFIG.id
  is 'ID , 没有业务含义';
comment on column DBAMON.TBL_TAB_PART_CONFIG.table_owner
  is '需要维护的表属主';
comment on column DBAMON.TBL_TAB_PART_CONFIG.table_name
  is '需要维护的表名';
comment on column DBAMON.TBL_TAB_PART_CONFIG.partition_column_type
  is '分区列类型, 支持VARCHAR2和DATE,TIMESTAMP,CHAR,VARCHAR,类型';
comment on column DBAMON.TBL_TAB_PART_CONFIG.partition_pre
  is '分区名前缀';
comment on column DBAMON.TBL_TAB_PART_CONFIG.partition_type
  is '分区类型,月, 1 天,10天,5天,, WEEK';
comment on column DBAMON.TBL_TAB_PART_CONFIG.drop_time_units
  is '保留分区个数';
comment on column DBAMON.TBL_TAB_PART_CONFIG.add_time_units
  is '增加分区个数';
comment on column DBAMON.TBL_TAB_PART_CONFIG.tablespace_name
  is '表空间';
comment on column DBAMON.TBL_TAB_PART_CONFIG.index_tb_name
  is '所音表空间';
comment on column DBAMON.TBL_TAB_PART_CONFIG.valid_flg
  is '可用标记 1 加删 2不加不删,3分区只加不删,4 只删不加';
comment on column DBAMON.TBL_TAB_PART_CONFIG.config_type
  is 'test,and run';
comment on column DBAMON.TBL_TAB_PART_CONFIG.format
  is '分区类型为字符的格式YYYYMM或者YYYY-MM';
comment on column DBAMON.TBL_TAB_PART_CONFIG.shour
  is 'start hour 0-23';
comment on column DBAMON.TBL_TAB_PART_CONFIG.ehour
  is 'end hour 1-24';
-- Create/Recreate primary, unique and foreign key constraints 
alter table DBAMON.TBL_TAB_PART_CONFIG
  add constraint PK_TAB_PART_ID primary key (ID)
  using index;
alter table DBAMON.TBL_TAB_PART_CONFIG
  add constraint C_CHECK_CONFIG
  check (PARTITION_TYPE  IN ('MONTH','DAY','TEN','WEEK','FIVE'));
alter table DBAMON.TBL_TAB_PART_CONFIG
  add constraint C_COLUMN_TYPE
  check (PARTITION_COLUMN_TYPE IN ('VARCHAR2','DATE'));
alter table DBAMON.TBL_TAB_PART_CONFIG
  add constraint C_EHOUR
  check (EHOUR IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24) AND EHOUR>SHOUR);
alter table DBAMON.TBL_TAB_PART_CONFIG
  add constraint C_SHOUR
  check (SHOUR IN (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23));


-- Create table
create table DBAMON.TBL_PART_MANAGE_SQL
(
  gid            NUMBER(10),
  table_owner    VARCHAR2(30),
  table_name     VARCHAR2(50),
  partition_name VARCHAR2(100),
  max_date       VARCHAR2(20),
  sql_text       VARCHAR2(4000),
  create_time    DATE,
  order_id       NUMBER(10) not null,
  resultmsg      VARCHAR2(100)
);

-- Create/Recreate indexes 
create index DBAMON.IDX_SQLCREATETIME on DBAMON.TBL_PART_MANAGE_SQL (CREATE_TIME);
-- Create/Recreate primary, unique and foreign key constraints 
alter table DBAMON.TBL_PART_MANAGE_SQL
  add primary key (ORDER_ID)
  using index ;


-- Create table
create table DBAMON.TBL_PART_ERR
(
  proc_name   VARCHAR2(100),
  errmsg      VARCHAR2(100),
  sample_time DATE
);


-- Create table
create table DBAMON.TBL_CONFIG_LOG
(
  config_time      DATE,
  username         VARCHAR2(50),
  oseruser         VARCHAR2(50),
  proxy_user       VARCHAR2(50),
  ip_addr          VARCHAR2(100),
  machine          VARCHAR2(50),
  table_owner      VARCHAR2(50),
  table_name       VARCHAR2(50),
  drop_time_units  NUMBER(3),
  policy           NUMBER(3),
  v_start_time     NUMBER(3),
  v_end_time       NUMBER(3),
  v_partition_type VARCHAR2(30),
  v_tab_tbs        VARCHAR2(50),
  v_inx_tbs        VARCHAR2(50),
  config_result    VARCHAR2(2000)
);


create sequence DBAMON.SEQ_TM_PART_MAINTEN
minvalue 1
maxvalue 100000
start with 1
increment by 1
cache 5
cycle;


create sequence DBAMON.SEQ_SQL_ORDER
minvalue 1
maxvalue 10000000
start with 1
increment by 1
cache 20;



CREATE OR REPLACE PACKAGE BODY DBAMON.PKG_MAINTEN_PART as
  --增加按月分区的SQL
  PROCEDURE STP_ADD_MON_DT AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_hour            number(2);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
    ---v4 分区指定表空间对于子分区SQL 可能会报错。修改未指定表空间的分区SQL不指定表空间。
    --- author: bobo at 2014-09-10
    ---v5  varchange
  BEGIN
    /*delete tbl_part_manage_sql;*/
    commit;
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'MONTH'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname := rm.table_name;
      v_maxpart  := null;
      v_tempower := rm.table_owner;

      --- 获取分区最大值
      v_currmax_date := null;
      v_isdefault    := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);

        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_currmax_date <= v_part_date or v_currmax_date is null then
            v_currmax_date := v_part_date;
          end if;
        end if;
      end loop;
      ---如果配置表里表空间为空,不指定表空间参数
      if rm.tablespace_name is null then
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      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 dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (to_date(''' ||
                     v_partdate || ''',''YYYY-MM-DD HH24:MI:SS''))' ||
                     v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (to_date(''' || v_partdate ||
                     ''', ''YYYY-MM-DD HH24:MI:SS''))  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引
              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                 cur_part_ind.index_name || ' rebuild partition ' ||
                 cur_part_ind.partition_name || ' tablespace ' ||
                 cur_part_ind.tablespace_name || ' parallel 4';
        begin
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录操作日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempower,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_MON_DT;
  PROCEDURE STP_ADD_DAY_DT AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_hour            number(2);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'DAY'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg IN (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname     := rm.table_name;
      v_currmax_date := null;
      v_tempower     := rm.table_owner;

      --- 获取分区最大值

      v_isdefault := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;

        else
          ---获取分区的MAX_VALUE.转化成DATE类型
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          ----判断是否分区最大值
          if v_currmax_date <= v_part_date or v_currmax_date is null then
            v_currmax_date := v_part_date;
          end if;
        end if;
      end loop;
      ---获取表空间名字
      if rm.tablespace_name is null then
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      while (v_currmax_date - rm.add_time_units <= trunc(sysdate)) loop

        v_partname     := to_char(trunc(v_currmax_date), 'YYYYMMDD');
        v_partdate     := to_char(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 dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt <> 0) then
          v_partname := v_partname || 's';
        end if;
        if v_isdefault = 'FALSE' then
          v_sql := 'alter table ' || rm.table_owner || '.' || rm.table_name ||
                   ' add partition ' || rm.partition_pre || v_partname ||
                   ' values less than (to_date(''' || v_partdate ||
                   ''',''YYYY-MM-DD HH24:MI:SS''))' || v_tablespace_name;

        elsif v_isdefault = 'TRUE' then
          v_sql := 'alter table ' || rm.table_owner || '.' || rm.table_name ||
                   ' split partition ' || v_maxpart || ' at (to_date(''' ||
                   v_partdate ||
                   ''', ''YYYY-MM-DD HH24:MI:SS''))  into (partition ' ||
                   rm.partition_pre || v_partname || ',partition ' ||
                   v_maxpart || ')';
        end if;

        ---执行加分区的SQL
        begin
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           rm.table_owner,
           rm.table_name,
           rm.partition_pre || v_partname,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);

        --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
        if (rm.index_tb_name is not null) then
          for cur_part_ind in (select distinct a.index_owner, a.index_name
                               /* a.index_owner,
                               a.index_name,
                               a.partition_name,
                               a.tablespace_name,
                               a.status*/
                                 from dba_ind_partitions a, dba_indexes b
                                where a.index_owner = b.owner
                                  and a.index_name = b.index_name
                                  and b.table_name = rm.table_name
                                  and a.index_owner = rm.table_owner
                               /*and a.partition_name =
                               rm.partition_pre || v_partname*/
                               ) loop
            v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                     cur_part_ind.index_name || ' rebuild partition ' ||
                     rm.partition_pre || v_partname || ' tablespace ' ||
                     rm.index_tb_name;
            --- 执行SQL 重建索引

            begin
              if rm.config_Type = 'TEST' then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' then
                v_errmsg := 'OK';
                execute immediate v_sql;
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               rm.table_owner,
               rm.table_name,
               rm.partition_pre || v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end loop;
        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        begin
          v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                   cur_part_ind.index_name || ' rebuild partition ' ||
                   cur_part_ind.partition_name || ' tablespace ' ||
                   cur_part_ind.tablespace_name;
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_DAY_DT;
  PROCEDURE STP_ADD_DAY_VAR AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_hour            number(2);
    v_current_maxval  varchar2(3000);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'DAY'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg IN (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname := rm.table_name;
      v_tempower := rm.table_owner;

      --- 获取分区最大值

      v_isdefault      := 'FALSE';
      v_current_maxval := null;
      v_currmax_date   := null;
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        elsif v_current_maxval < v_high_value or v_current_maxval is null then
          v_current_maxval := v_high_value;
        end if;
      end loop;
      if rm.format = 'YYYY-MM-DD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 10),
                               'YYYY-MM-DD');
      elsif rm.format = 'YYYYMMDD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 8), 'YYYYMMDD');
      end if;
      v_currmax_date := v_part_date;
      ---如果配置表里表空间为空,找出该表目前所用表空间
      if rm.tablespace_name is null then
        /*        select tablespace_name
         into v_tablespace_name
         from dba_tab_partitions
        where table_owner = rm.table_owner
          and table_name = rm.table_name
          and rownum = 1;*/
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      while (v_currmax_date - rm.add_time_units <= trunc(sysdate)) loop

        v_partname := to_char(trunc(v_currmax_date), 'YYYYMMDD');
        if rm.format = 'YYYY-MM-DD' then
          v_partdate := to_char(trunc(v_currmax_date) + 1, 'YYYY-MM-DD');
        elsif rm.format = 'YYYYMMDD' then
          v_partdate := to_char(trunc(v_currmax_date) + 1, 'YYYYMMDD');
        end if;
        v_currmax_date := v_currmax_date + 1;
        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (''' || v_partdate ||
                     ''')  ' || v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (''' || v_partdate || '''  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                 /* a.index_owner,
                                 a.index_name,
                                 a.partition_name,
                                 a.tablespace_name,
                                 a.status*/
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner
                                 /*and a.partition_name =
                                 rm.partition_pre || v_partname*/
                                 ) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引

              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        begin
          v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                   cur_part_ind.index_name || ' rebuild partition ' ||
                   cur_part_ind.partition_name || ' tablespace ' ||
                   cur_part_ind.tablespace_name;
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_DAY_VAR;
  PROCEDURE STP_ADD_MON_VAR AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempowner       varchar2(100);
    v_tempname        varchar2(50);
    v_hour            number(2);
    v_current_maxval  varchar2(3000);
    ---V1:var类型的分区MAXVALUE 字段有两种,一种是YYYY-MM,另外一种是YYYYMM. 需要分别处理。
    ---
  BEGIN
    ---删除SQL,测试用
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual; --获取本次处理的ID

    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'MONTH'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg in (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempowner := rm.table_owner;
      v_tempname  := rm.table_name;
      v_isdefault := 'FALSE';
      --v_currmax_date   := null;
      v_current_maxval := null;
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        -- 获取当前分区的最大值, 转化为DATE类型
        v_high_value := substr(cur_part.high_value, 1, 2000);

        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        elsif v_current_maxval < v_high_value or v_current_maxval is null then
          v_current_maxval := v_high_value;
        end if;
      end loop;
      if rm.format = 'YYYY-MM' then
        v_part_date := to_date(substr(v_current_maxval, 2, 7), 'YYYY-MM');
      elsif rm.format = 'YYYYMM' then
        v_part_date := to_date(substr(v_current_maxval, 2, 6), 'YYYYMM');
      end if;
      v_currmax_date := v_part_date;
      --如果配置表里表空间为空,找出该表目前所用表空间
      if rm.tablespace_name is null then
        select tablespace_name
          into v_tablespace_name
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and 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');
        if rm.format = 'YYYY-MM' THEN
          v_partdate := to_char(trunc(add_months(v_currmax_date, 1)),
                                'YYYY-MM');
        elsif rm.format = 'YYYYMM' THEN
          v_partdate := to_char(trunc(add_months(v_currmax_date, 1)),
                                'YYYYMM');
        end if;
        v_currmax_date := add_months(v_currmax_date, 1);

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

        if (v_partition_cnt = 0) then
          -- ADD 分区
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (''' || v_partdate ||
                     ''') tablespace ' || v_tablespace_name;
          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at ''' || v_partdate || '''  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);
          commit;
          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                 /* a.index_owner,
                                 a.index_name,
                                 a.partition_name,
                                 a.tablespace_name,
                                 a.status*/
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner
                                 /*and a.partition_name =
                                 rm.partition_pre || v_partname*/
                                 ) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;

              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop

        v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                 cur_part_ind.index_name || ' rebuild partition ' ||
                 cur_part_ind.partition_name || ' tablespace ' ||
                 cur_part_ind.tablespace_name;
        begin

          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           v_tempowner,
           v_tempname,
           v_partname,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;

      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempowner,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_MON_VAR;

  PROCEDURE STP_DEL_MON AS
    v_currmax_date date;
    v_high_value   varchar2(4000);

    v_part_date date;
    v_drop_date date;
    v_partname  varchar2(50);
    v_partdate  varchar2(10);
    v_id        number;
    v_sql       varchar2(1000);
    v_errmsg    varchar2(1000);
    v_tempowner varchar2(100);
    v_tempname  varchar2(50);
    v_hour      number(2);
    v_dropval   varchar2(50);
    v_count     NUMBER;
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    --处理DATE类型的分区表
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type IN ('MONTH')
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 4)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop

      v_tempname     := rm.table_name;
      v_tempowner    := rm.table_owner;
      v_currmax_date := null;
      --获取删除的最大DATE
      v_drop_date := add_months(trunc(sysdate, 'MM'), -rm.drop_time_units);

      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        if v_high_value = 'MAXVALUE' then
          null;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_drop_date >= v_part_date then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := to_char(v_part_date, 'YYYY-MM-DD');
            ---if there is any global index.
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'MONTH'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg in (1, 4)) loop
      v_tempname  := rm.table_name;
      v_tempowner := rm.table_owner;
      v_drop_date := add_months(trunc(sysdate, 'MM'), -rm.drop_time_units);
      if rm.format = 'YYYY-MM' then
        v_dropval := ''''||TO_CHAR(v_drop_date, 'YYYY-MM')||'''';
      elsif rm.format = 'YYYYMM' then
        v_dropval := ''''||TO_CHAR(v_drop_date, 'YYYYMM')||'''';
      elsif rm.format = 'YYYYMMDD' then
        v_dropval := ''''||TO_CHAR(v_drop_date, 'YYYYMMDD')||'''';
      elsif rm.format = 'YYYY-MM-DD' then
        v_dropval := ''''||TO_CHAR(v_drop_date, 'YYYY-MM-DD')||'''';
      end if;
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 2000);

        if v_high_value = 'MAXVALUE' then
          null;
        else
          if v_dropval >= v_high_value then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := v_high_value;
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                 cur_part_ind.index_name || ' rebuild partition ' ||
                 cur_part_ind.partition_name || ' tablespace ' ||
                 cur_part_ind.tablespace_name;
        if rm.config_Type = 'TEST' then
          v_errmsg := 'TEST';
        elsif rm.config_type = 'RUN' then
          v_errmsg := 'OK';
          execute immediate v_sql;
        end if;
      end loop;
    end loop;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempowner,
         v_tempname,
         'ALL',
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_DEL_MON;

  PROCEDURE STP_DEL_DAY AS
    v_currmax_date date;
    v_high_value   varchar2(4000);
    v_part_date    date;
    v_drop_date    date;
    v_id           number;
    v_sql          varchar2(1000);
    v_errmsg       varchar2(1000);
    v_tempowner    varchar2(100);
    v_tempname     varchar2(50);
    v_partname     varchar2(50);
    v_partdate     varchar2(20);
    v_hour         number(2);
    v_dropval      varchar2(50);
    v_count        NUMBER;
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'DAY'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 4)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop

      v_tempname     := rm.table_name;
      v_tempowner    := rm.table_owner;
      v_currmax_date := null;
      v_drop_date    := trunc(sysdate, 'DD') - rm.drop_time_units;

      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        if v_high_value = 'MAXVALUE' then
          null;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_drop_date >= v_part_date then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := to_char(v_part_date, 'YYYY-MM-DD');
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'DAY'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg in (1, 4)) loop
      v_tempname     := rm.table_name;
      v_currmax_date := null;
      v_drop_date    := trunc(sysdate) - rm.drop_time_units;
      if rm.format = 'YYYY-MM-DD' THEN
        v_dropval := ''''||to_char(v_drop_date, 'YYYY-MM-DD')||'''';
      elsif rm.format = 'YYYYMMDD' THEN
        v_dropval := ''''||to_char(v_drop_date, 'YYYYMMDD')||'''';
      end if;
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 2000);

        if v_high_value = 'MAXVALUE' then
          null;
        else

          if v_dropval >= v_high_value then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := v_high_value;
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录操作日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempowner,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_DEL_DAY;
  PROCEDURE STP_ADD_WEEK_DT AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_hour            number(2);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
    ---v4 分区指定表空间对于子分区SQL 可能会报错。修改未指定表空间的分区SQL不指定表空间。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'WEEK'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname := rm.table_name;
      v_maxpart  := null;
      v_tempower := rm.table_owner;

      --- 获取分区最大值
      v_currmax_date := null;
      v_isdefault    := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);

        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_currmax_date <= v_part_date or v_currmax_date is null then
            v_currmax_date := v_part_date;
          end if;
        end if;
      end loop;
      ---如果配置表里表空间为空,不指定表空间参数
      if rm.tablespace_name is null then
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      while (v_currmax_date - rm.add_time_units * 7 <= SYSDATE) loop

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

        v_currmax_date := v_currmax_date + 7;
        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (to_date(''' ||
                     v_partdate || ''',''YYYY-MM-DD HH24:MI:SS''))' ||
                     v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (to_date(''' || v_partdate ||
                     ''', ''YYYY-MM-DD HH24:MI:SS''))  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引
              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                 cur_part_ind.index_name || ' rebuild partition ' ||
                 cur_part_ind.partition_name || ' tablespace ' ||
                 cur_part_ind.tablespace_name;
        begin
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录操作日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempower,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_WEEK_DT;
  PROCEDURE STP_ADD_WEEK_VAR AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_hour            number(2);
    v_current_maxval  varchar2(3000);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'WEEK'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg IN (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname       := rm.table_name;
      v_currmax_date   := null;
      v_tempower       := rm.table_owner;
      v_current_maxval := null;
      --- 获取分区最大值
      v_isdefault := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        elsif v_current_maxval < v_high_value or v_current_maxval is null then
          v_current_maxval := v_high_value;
        end if;
      end loop;

      ---transfer to date
      if rm.format = 'YYYY-MM-DD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 10),
                               'YYYY-MM-DD');
      elsif rm.format = 'YYYYMMDD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 8), 'YYYYMMDD');
      end if;
      v_currmax_date := v_part_date;
      ---如果配置表里表空间为空,找出该表目前所用表空间
      if rm.tablespace_name is null then
        /*        select tablespace_name
         into v_tablespace_name
         from dba_tab_partitions
        where table_owner = rm.table_owner
          and table_name = rm.table_name
          and rownum = 1;*/
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      while (v_currmax_date - rm.add_time_units * 7 <= trunc(sysdate)) loop

        v_partname := to_char(trunc(v_currmax_date), 'YYYYMMDD');
        if rm.format = 'YYYY-MM-DD' then
          v_partdate := to_char(trunc(v_currmax_date) + 7, 'YYYY-MM-DD');
        elsif rm.format = 'YYYYMMDD' then
          v_partdate := to_char(trunc(v_currmax_date) + 7, 'YYYYMMDD');
        end if;
        v_currmax_date := v_currmax_date + 7;
        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (''' || v_partdate ||
                     ''')  ' || v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (''' || v_partdate || '''  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                 /* a.index_owner,
                                 a.index_name,
                                 a.partition_name,
                                 a.tablespace_name,
                                 a.status*/
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner
                                 /*and a.partition_name =
                                 rm.partition_pre || v_partname*/
                                 ) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引

              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        begin
          v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                   cur_part_ind.index_name || ' rebuild partition ' ||
                   cur_part_ind.partition_name || ' tablespace ' ||
                   cur_part_ind.tablespace_name;
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_WEEK_VAR;
  PROCEDURE STP_ADD_FIVE_DT AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_units           number;
    v_hour            number(2);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
    ---v4 分区指定表空间对于子分区SQL 可能会报错。修改未指定表空间的分区SQL不指定表空间。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'FIVE'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname := rm.table_name;
      v_maxpart  := null;
      v_tempower := rm.table_owner;
      v_units    := trunc(TO_NUMBER(TO_CHAR(sysdate, 'DD')) / 5) + 1 +
                    rm.add_time_units;

      --- 获取分区最大值
      v_currmax_date := null;
      v_isdefault    := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);

        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_currmax_date <= v_part_date or v_currmax_date is null then
            v_currmax_date := v_part_date;
          end if;
        end if;
      end loop;
      ---如果配置表里表空间为空,不指定表空间参数
      if rm.tablespace_name is null then
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      while (v_currmax_date <=
            add_months(trunc(sysdate, 'MM'), trunc(v_units / 6)) +
            mod(v_units, 6) * 5) loop

        if trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 0 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'A';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 1 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'B';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 2 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'C';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 3 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'D';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 4 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'E';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 5 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'F';
          v_partdate     := TO_CHAR(ADD_MONTHS(trunc(v_currmax_date, 'MM'),
                                               1),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := ADD_MONTHS(trunc(v_currmax_date, 'MM'), 1);
        end if;

        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (to_date(''' ||
                     v_partdate || ''',''YYYY-MM-DD HH24:MI:SS''))' ||
                     v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (to_date(''' || v_partdate ||
                     ''', ''YYYY-MM-DD HH24:MI:SS''))  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);
          COMMIT;
          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引
              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;
        end if;
      end loop;
    end loop;
  end STP_ADD_FIVE_DT;
  PROCEDURE STP_ADD_FIVE_VAR AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_units           number;
    v_hour            number(2);
    v_current_maxval  varchar2(3000);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3  对于11G 的新建分区不做判断, 直接处理。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'FIVE'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg IN (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname       := rm.table_name;
      v_tempower       := rm.table_owner;
      v_current_maxval := null;
      --- 获取分区最大值

      v_isdefault := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        elsif v_current_maxval < v_high_value or v_current_maxval is null then
          v_current_maxval := v_high_value;
        end if;
      end loop;
      ---transfer to date
      if rm.format = 'YYYY-MM-DD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 10),
                               'YYYY-MM-DD');
      elsif rm.format = 'YYYYMMDD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 8), 'YYYYMMDD');
      end if;
      v_currmax_date := v_part_date;
      ---如果配置表里表空间为空,找出该表目前所用表空间
      if rm.tablespace_name is null then
        /*        select tablespace_name
         into v_tablespace_name
         from dba_tab_partitions
        where table_owner = rm.table_owner
          and table_name = rm.table_name
          and rownum = 1;*/
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      v_units := trunc(TO_NUMBER(TO_CHAR(sysdate, 'DD')) / 5) + 1 +
                 rm.add_time_units;
      while (v_currmax_date - rm.add_time_units <=
            add_months(trunc(sysdate, 'MM'), trunc(v_units / 6)) +
            mod(v_units, 6) * 10) loop
        if trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 0 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'A';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 1 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'B';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 2 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'C';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 3 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'D';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 4 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'E';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 5),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 5;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 5) = 5 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'F';
          v_partdate     := TO_CHAR(ADD_MONTHS(trunc(v_currmax_date, 'MM'),
                                               1),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := ADD_MONTHS(trunc(v_currmax_date, 'MM'), 1);
        end if;
        if rm.format = 'YYYY-MM-DD' then
          v_partdate := to_char(trunc(v_currmax_date), 'YYYY-MM-DD');
        elsif rm.format = 'YYYYMMDD' then
          v_partdate := to_char(trunc(v_currmax_date), 'YYYYMMDD');
        end if;
        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (''' || v_partdate ||
                     ''')  ' || v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (''' || v_partdate || '''  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                 /* a.index_owner,
                                 a.index_name,
                                 a.partition_name,
                                 a.tablespace_name,
                                 a.status*/
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner
                                 /*and a.partition_name =
                                 rm.partition_pre || v_partname*/
                                 ) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引

              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        begin
          v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                   cur_part_ind.index_name || ' rebuild partition ' ||
                   cur_part_ind.partition_name || ' tablespace ' ||
                   cur_part_ind.tablespace_name;
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_FIVE_VAR;
  PROCEDURE STP_DEL_WEEK AS
    v_currmax_date date;
    v_high_value   varchar2(4000);
    v_part_date    date;
    v_drop_date    date;
    v_id           number;
    v_sql          varchar2(1000);
    v_errmsg       varchar2(1000);
    v_tempowner    varchar2(100);
    v_tempname     varchar2(50);
    v_partname     varchar2(50);
    v_partdate     varchar2(20);
    v_hour         number(2);
    v_dropvalue    varchar2(40);
    v_count        NUMBER;
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'WEEK'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 4)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop

      v_tempname     := rm.table_name;
      v_tempowner    := rm.table_owner;
      v_currmax_date := null;
      v_drop_date    := trunc(sysdate) - rm.drop_time_units * 7;

      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        if v_high_value = 'MAXVALUE' then
          null;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_drop_date >= v_part_date then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := to_char(v_part_date, 'YYYY-MM-DD');
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'WEEK'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg in (1, 4)) loop
      v_tempname     := rm.table_name;
      v_currmax_date := null;
      v_drop_date    := trunc(sysdate) - rm.drop_time_units * 7;

      if rm.format = 'YYYY-MM-DD' THEN
        v_dropvalue := ''''||to_char(v_drop_date, 'YYYY-MM-DD')||'''';
      elsif rm.format = 'YYYYMMDD' THEN
        v_dropvalue := ''''||to_char(v_drop_date, 'YYYYMMDD')||'''';
      end if;
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 2000);

        if v_high_value = 'MAXVALUE' then
          null;
        else
          if v_dropvalue > v_high_value then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := v_high_value;
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录操作日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempowner,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_DEL_WEEK;
  PROCEDURE STP_ADD_TEN_DT AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_units           number;
    v_hour            number(2);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3 分区自动维护加分区会有问题。不再判断, 允许报错。
    ---v4 分区指定表空间对于子分区SQL 可能会报错。修改未指定表空间的分区SQL不指定表空间。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'TEN'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname := rm.table_name;
      v_maxpart  := null;
      v_tempower := rm.table_owner;
      v_units    := trunc(TO_NUMBER(TO_CHAR(sysdate, 'DD')) / 10) + 1 +
                    rm.add_time_units;

      --- 获取分区最大值
      v_currmax_date := null;
      v_isdefault    := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);

        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_currmax_date <= v_part_date or v_currmax_date is null then
            v_currmax_date := v_part_date;
          end if;
        end if;
      end loop;
      ---如果配置表里表空间为空,不指定表空间参数
      if rm.tablespace_name is null then
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      while (v_currmax_date <=
            add_months(trunc(sysdate, 'MM'), trunc(v_units / 3)) +
            mod(v_units, 3) * 10) loop

        if trunc(to_number(to_char(v_currmax_date, 'DD')) / 10) = 0 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'A';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 10),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 10;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 10) = 1 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'B';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 10),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 10;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 10) = 2 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'C';
          v_partdate     := TO_CHAR(ADD_MONTHS(trunc(v_currmax_date, 'MM'),
                                               1),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := ADD_MONTHS(trunc(v_currmax_date, 'MM'), 1);
        end if;

        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (to_date(''' ||
                     v_partdate || ''',''YYYY-MM-DD HH24:MI:SS''))' ||
                     v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (to_date(''' || v_partdate ||
                     ''', ''YYYY-MM-DD HH24:MI:SS''))  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引
              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                 cur_part_ind.index_name || ' rebuild partition ' ||
                 cur_part_ind.partition_name || ' tablespace ' ||
                 cur_part_ind.tablespace_name;
        begin
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录操作日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempower,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_TEN_DT;
  PROCEDURE STP_ADD_TEN_VAR AS
    v_currmax_date    date;
    v_partdate        varchar2(20);
    v_high_value      varchar2(4000);
    v_partname        varchar2(30);
    v_part_date       date;
    v_tablespace_name varchar2(80);
    v_partition_cnt   number(10);
    v_tempname        varchar2(50);
    v_id              number;
    v_isdefault       varchar2(20);
    v_sql             varchar2(1000);
    v_errmsg          varchar2(1000);
    v_maxpart         varchar2(100);
    v_tempower        varchar2(100);
    v_units           number;
    v_hour            number(2);
    v_current_maxval  varchar2(3000);
    ---v1  tbl_part_manage_sql 修改为日志表。 记录执行时的日志。增加执行时的判断,记录报错信息。
    ---v2  考虑split分区的情况,
    ---v3  对于11G 的新建分区不做判断, 直接处理。
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'TEN'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg IN (1, 3)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop
      v_tempname       := rm.table_name;
      v_tempower       := rm.table_owner;
      v_current_maxval := null;
      --- 获取分区最大值

      v_isdefault := 'FALSE';
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        --- 判断是否存在MAXVALUE, 如果存在则只能使用SPLIT分区,记录DEFAULT 分区名字
        if v_high_value = 'MAXVALUE' then
          v_isdefault := 'TRUE';
          v_maxpart   := cur_part.partition_name;
        elsif v_current_maxval < v_high_value or v_current_maxval is null then
          v_current_maxval := v_high_value;
        end if;
      end loop;
      ---transfer to date
      if rm.format = 'YYYY-MM-DD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 10),
                               'YYYY-MM-DD');
      elsif rm.format = 'YYYYMMDD' then
        v_part_date := to_date(substr(v_current_maxval, 2, 8), 'YYYYMMDD');
      end if;
      v_currmax_date := v_part_date;
      ---如果配置表里表空间为空,找出该表目前所用表空间
      if rm.tablespace_name is null then
        /*        select tablespace_name
         into v_tablespace_name
         from dba_tab_partitions
        where table_owner = rm.table_owner
          and table_name = rm.table_name
          and rownum = 1;*/
        v_tablespace_name := '';
      else
        v_tablespace_name := ' tablespace ' || rm.tablespace_name;
      end if;
      ---生成加分区SQL并执行。
      v_units := trunc(TO_NUMBER(TO_CHAR(sysdate, 'DD')) / 10) + 1 +
                 rm.add_time_units;
      while (v_currmax_date - rm.add_time_units <=
            add_months(trunc(sysdate, 'MM'), trunc(v_units / 3)) +
            mod(v_units, 3) * 10) loop
        if trunc(to_number(to_char(v_currmax_date, 'DD')) / 10) = 0 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'A';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 10),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 10;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 10) = 1 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'B';
          v_partdate     := TO_CHAR(trunc(v_currmax_date + 10),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := v_currmax_date + 10;
        elsif trunc(to_number(to_char(v_currmax_date, 'DD')) / 10) = 2 then
          v_partname     := to_char(trunc(v_currmax_date), 'YYYYMM') || 'C';
          v_partdate     := TO_CHAR(ADD_MONTHS(trunc(v_currmax_date, 'MM'),
                                               1),
                                    'YYYY-MM-DD HH24:MI:SS');
          v_currmax_date := ADD_MONTHS(trunc(v_currmax_date, 'MM'), 1);
        end if;
        if rm.format = 'YYYY-MM-DD' then
          v_partdate := to_char(trunc(v_currmax_date), 'YYYY-MM-DD');
        elsif rm.format = 'YYYYMMDD' then
          v_partdate := to_char(trunc(v_currmax_date), 'YYYYMMDD');
        end if;
        select count(1)
          into v_partition_cnt
          from dba_tab_partitions
         where table_owner = rm.table_owner
           and table_name = rm.table_name
           and partition_name = rm.partition_pre || v_partname;
        if (v_partition_cnt = 0) then
          if v_isdefault = 'FALSE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' add partition ' || rm.partition_pre ||
                     v_partname || ' values less than (''' || v_partdate ||
                     ''')  ' || v_tablespace_name;

          elsif v_isdefault = 'TRUE' then
            v_sql := 'alter table ' || rm.table_owner || '.' ||
                     rm.table_name || ' split partition ' || v_maxpart ||
                     ' at (''' || v_partdate || '''  into (partition ' ||
                     rm.partition_pre || v_partname || ',partition ' ||
                     v_maxpart || ')';
          end if;

          ---执行加分区的SQL
          begin
            if rm.config_Type = 'TEST' then
              v_errmsg := 'TEST';
            elsif rm.config_type = 'RUN' then
              v_errmsg := 'OK';
              execute immediate v_sql;
            end if;
          exception
            when others then
              v_errmsg := substr(sqlerrm, 1, 60);
          end;
          ---纪录操作日志
          insert into TBL_PART_MANAGE_SQL
            (gid,
             table_owner,
             table_name,
             partition_name,
             max_date,
             sql_text,
             create_time,
             order_id,
             resultmsg)
          values
            (v_id,
             rm.table_owner,
             rm.table_name,
             rm.partition_pre || v_partname,
             v_partdate,
             v_sql || ';',
             sysdate,
             seq_sql_order.nextval,
             v_errmsg);

          --如果配置了索引表空间索引,索引分区需rebuild到指定的索引表空间
          if (rm.index_tb_name is not null) then
            for cur_part_ind in (select distinct a.index_owner, a.index_name
                                 /* a.index_owner,
                                 a.index_name,
                                 a.partition_name,
                                 a.tablespace_name,
                                 a.status*/
                                   from dba_ind_partitions a, dba_indexes b
                                  where a.index_owner = b.owner
                                    and a.index_name = b.index_name
                                    and b.table_name = rm.table_name
                                    and a.index_owner = rm.table_owner
                                 /*and a.partition_name =
                                 rm.partition_pre || v_partname*/
                                 ) loop
              v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                       cur_part_ind.index_name || ' rebuild partition ' ||
                       rm.partition_pre || v_partname || ' tablespace ' ||
                       rm.index_tb_name;
              --- 执行SQL 重建索引

              begin
                if rm.config_Type = 'TEST' then
                  v_errmsg := 'TEST';
                elsif rm.config_type = 'RUN' then
                  v_errmsg := 'OK';
                  execute immediate v_sql;
                end if;
              exception
                when others then
                  v_errmsg := substr(sqlerrm, 1, 60);
              end;
              ---纪录操作日志
              insert into TBL_PART_MANAGE_SQL
                (gid,
                 table_owner,
                 table_name,
                 partition_name,
                 max_date,
                 sql_text,
                 create_time,
                 order_id,
                 resultmsg)
              values
                (v_id,
                 rm.table_owner,
                 rm.table_name,
                 rm.partition_pre || v_partname,
                 v_partdate,
                 v_sql || ';',
                 sysdate,
                 seq_sql_order.nextval,
                 v_errmsg);
              commit;
            end loop;
          end if;

        end if;
      end loop;

      --重建不可用的局部索引
      for cur_part_ind in (select a.index_owner,
                                  a.index_name,
                                  a.partition_name,
                                  a.tablespace_name,
                                  a.status
                             from dba_ind_partitions a, dba_indexes b
                            where a.index_owner = b.owner
                              and a.index_name = b.index_name
                              and b.table_name = rm.table_name
                              and b.table_owner = rm.table_owner
                              and a.status = 'UNUSABLE') loop
        begin
          v_sql := 'alter index ' || cur_part_ind.index_owner || '.' ||
                   cur_part_ind.index_name || ' rebuild partition ' ||
                   cur_part_ind.partition_name || ' tablespace ' ||
                   cur_part_ind.tablespace_name;
          if rm.config_Type = 'TEST' then
            v_errmsg := 'TEST';
          elsif rm.config_type = 'RUN' then
            v_errmsg := 'OK';
            execute immediate v_sql;
          end if;
        exception
          when others then
            v_errmsg := substr(sqlerrm, 1, 60);
        end;
        ---纪录操作日志
        insert into TBL_PART_MANAGE_SQL
          (gid,
           table_owner,
           table_name,
           partition_name,
           max_date,
           sql_text,
           create_time,
           order_id,
           resultmsg)
        values
          (v_id,
           cur_part_ind.index_owner,
           cur_part_ind.index_name,
           cur_part_ind.partition_name,
           v_partdate,
           v_sql || ';',
           sysdate,
           seq_sql_order.nextval,
           v_errmsg);
        commit;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录异常日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempower,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_ADD_TEN_VAR;

  PROCEDURE STP_DEL_TEN AS
    v_currmax_date date;
    v_high_value   varchar2(4000);
    v_part_date    date;
    v_drop_date    date;
    v_id           number;
    v_sql          varchar2(1000);
    v_errmsg       varchar2(1000);
    v_tempowner    varchar2(100);
    v_tempname     varchar2(50);
    v_partname     varchar2(50);
    v_partdate     varchar2(20);
    v_units        number;
    v_hour         number(2);
    v_dropval      varchar2(40);
    v_count        NUMBER;
  BEGIN
    /*delete tbl_part_manage_sql;*/
    v_hour := to_number(to_char(sysdate, 'HH24'));
    select SEQ_TM_PART_MAINTEN.nextval into v_id from dual;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'TEN'
                  and p.partition_column_type = 'DATE'
                  and p.valid_flg in (1, 4)
                  and v_hour >= p.shour
                  and v_hour < p.ehour) loop

      v_tempname     := rm.table_name;
      v_tempowner    := rm.table_owner;
      v_currmax_date := null;

      ---获取需删除分区的最大日期
      v_units := trunc(TO_NUMBER(TO_CHAR(sysdate, 'DD')) / 10) + 1 -
                 rm.drop_time_units;

      if v_units < 0 then
        v_drop_date := ADD_MONTHS(trunc(sysdate, 'MM'),
                                  trunc(v_units / 3) - 1) +
                       (mod(v_units, 3) + 3) * 10;
      elsif v_units >= 0 then
        v_drop_date := trunc(sysdate, 'MM') + v_units * 10;
      end if;

      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 4000);
        if v_high_value = 'MAXVALUE' then
          null;
        else
          execute immediate 'select ' || v_high_value || ' from dual'
            into v_part_date;
          if v_drop_date >= v_part_date then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := to_char(v_part_date, 'YYYY-MM-DD');
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    for rm in (select distinct p.*
                 from tbl_tab_part_config p, dba_tab_partitions u
                where p.table_owner = u.table_owner
                  and p.table_name = u.table_name
                  and p.partition_type = 'TEN'
                  and p.partition_column_type = 'VARCHAR2'
                  and p.valid_flg in (1, 4)) loop
      v_tempname     := rm.table_name;
      v_currmax_date := null;
      ----获取分区最大日期的类型
      v_units := trunc(TO_NUMBER(TO_CHAR(sysdate, 'DD')) / 10) + 1 -
                 rm.drop_time_units;

      if v_units < 0 then
        v_drop_date := ADD_MONTHS(trunc(sysdate, 'MM'),
                                  trunc(v_units / 3) - 1) +
                       (mod(v_units, 3) + 3) * 10;
      elsif v_units >= 0 then
        v_drop_date := trunc(sysdate, 'MM') + v_units * 10;
      end if;
      if rm.format = 'YYYY-MM-DD' THEN
        v_dropval := ''''||to_char(v_drop_date, 'YYYY-MM-DD')||'''';
      elsif rm.format = 'YYYYMMDD' THEN
        v_dropval := ''''||to_char(v_drop_date, 'YYYYMMDD')||'''';
      end if;
      for cur_part in (select partition_name, high_value
                         from dba_tab_partitions
                        where table_owner = rm.table_owner
                          and table_name = rm.table_name
                        order by partition_name) loop
        v_high_value := substr(cur_part.high_value, 1, 2000);

        if v_high_value = 'MAXVALUE' then
          null;
        else

          if v_dropval >= v_high_value then
            v_sql      := 'alter table ' || rm.table_owner || '.' ||
                          rm.table_name || ' drop partition ' ||
                          cur_part.partition_name;
            v_partname := cur_part.partition_name;
            v_partdate := v_high_value;
            select count(*)
              into v_count
              from dba_indexes t
             where t.table_owner = RM.TABLE_OWNER
               AND T.table_name = rm.table_name
               and PARTITIONED = 'NO';
            begin
              if rm.config_Type = 'TEST' and v_count = 0 then
                v_errmsg := 'TEST';
              elsif rm.config_type = 'RUN' and v_count = 0 then
                v_errmsg := 'OK';
                execute immediate v_sql;
              else
                v_errmsg := 'GLOBAL_INDEXES';
                v_sql:=v_sql||' UPDATE GLOBAL INDEXES'; 
              end if;
            exception
              when others then
                v_errmsg := substr(sqlerrm, 1, 60);
            end;
            ---纪录操作日志
            insert into TBL_PART_MANAGE_SQL
              (gid,
               table_owner,
               table_name,
               partition_name,
               max_date,
               sql_text,
               create_time,
               order_id,
               resultmsg)
            values
              (v_id,
               v_tempowner,
               v_tempname,
               v_partname,
               v_partdate,
               v_sql || ';',
               sysdate,
               seq_sql_order.nextval,
               v_errmsg);
            commit;
          end if;
        end if;
      end loop;
    end loop;
    commit;
  exception
    when others then
      v_errmsg := substr(sqlerrm, 1, 60);
      ---纪录操作日志
      insert into TBL_PART_MANAGE_SQL
        (gid,
         table_owner,
         table_name,
         partition_name,
         max_date,
         sql_text,
         create_time,
         order_id,
         resultmsg)
      values
        (v_id,
         v_tempowner,
         v_tempname,
         v_partname,
         v_partdate,
         v_sql || ';',
         sysdate,
         seq_sql_order.nextval,
         v_errmsg);
      commit;
  END STP_DEL_TEN;
  PROCEDURE GATHER_TABLE_INFO(v_table_owner in varchar2,
                              v_table_name  in varchar2) AS
    v_high_value     varchar2(4000);
    v_isdefault      varchar2(30);
    v_maxpart        varchar2(60);
    v_minpart        varchar2(60);
    v_part_time      date;
    v_partmaxdate    varchar2(12);
    v_part2stdate    varchar2(12);
    v_partmindate    varchar2(12);
    v_current_maxval varchar2(3000);
    v_current_minval varchar2(3000);
    v_current_2stval varchar2(3000);
    v_partcol_type   varchar2(20);
    v_part_type      varchar2(10);
    v_format         varchar2(12);
    v_gi_count       number;
    v_partcol_name   varchar2(100);
    v_count          number;
    v_interval       varchar2(30);
  BEGIN
    delete dbamon.tbl_part_info
     where table_owner = v_table_owner
       and table_name = v_table_name;
    v_isdefault      := 'FALSE';
    v_current_maxval := null;
    v_current_minval := null;
    v_current_2stval := null;
    select count(*)
      into v_gi_count
      from dba_indexes t
     where t.table_owner = v_table_owner
       and t.table_name = v_table_name
       and t.partitioned <> 'YES';
    for cur_part in (select partition_name, high_value
                       from dba_tab_partitions
                      where table_owner = v_table_owner
                        and table_name = v_table_name
                      order by partition_name) loop
      v_high_value := substr(cur_part.high_value, 1, 4000);

      if v_high_value = 'MAXVALUE' then
        v_isdefault := 'TRUE';
      else
        if v_current_maxval is null then
          v_current_maxval := v_high_value;
          v_maxpart        := cur_part.partition_name;
        elsif v_current_maxval < v_high_value then
          v_current_2stval := v_current_maxval;
          v_current_maxval := v_high_value;
          v_maxpart        := cur_part.partition_name;
        elsif v_current_2stval < v_high_value then
          v_current_2stval := v_high_value;
        end if;
        if v_current_minval is null or v_current_minval >= v_high_value then
          v_current_minval := v_high_value;
          v_minpart        := cur_part.partition_name;
        end if;
      end if;
    end loop;
    v_format      := null;
    v_partmaxdate := null;
    v_partmindate := null;
    v_part2stdate := null;
    SELECT DATA_TYPE, t1.COLUMN_NAME
      INTO v_partcol_type, v_partcol_name
      fROM DBA_TAB_COLUMNS T1, DBA_PART_KEY_COLUMNS T2
     WHERE T1.OWNER = T2.OWNER
       AND T1.TABLE_NAME = T2.NAME
       AND T1.COLUMN_NAME = T2.COLUMN_NAME
       AND T1.TABLE_NAME = v_table_name
       AND T1.OWNER = v_table_owner
       and rownum < 2;
  /*  select count(*) into v_count from v$instance where version like '11%';*/
  v_count:=1;
    if v_count > 0 then
      execute immediate 'select interval  from dba_part_tables
          where owner=''' || v_table_owner ||
                        '''  and table_name=''' || v_table_name || ''''
        into v_interval;
    else
      v_interval := null;
    end if;

    if v_partcol_type = 'DATE' or v_partcol_type like 'TIMESTAMP%' then
      execute immediate 'select ' || v_current_maxval || '  from dual'
        into v_part_time;
      v_partmaxdate := to_char(v_part_time, 'YYYY-MM-DD');
      execute immediate 'select ' || v_current_minval || '  from dual'
        into v_part_time;
      v_partmindate := to_char(v_part_time, 'YYYY-MM-DD');
      if v_current_2stval is not null then
        execute immediate 'select ' || v_current_2stval || '  from dual'
          into v_part_time;
        v_part2stdate := to_char(v_part_time, 'YYYY-MM-DD');
      end if;
    elsif v_partcol_type = 'VARCHAR2' OR v_partcol_type = 'VARCHAR' or
          v_partcol_type = 'CHAR' then
      if length(v_current_maxval) = 9 and
         substr(v_current_maxval, 6, 1) = '-' then
        v_format      := 'YYYY-MM';
        v_partmaxdate := REPLACE(v_current_maxval, '''', NULL) || '-01';
      elsif length(v_current_maxval) = 8 and
            instr(v_current_maxval, '-') = 0 then
        v_format      := 'YYYYMM';
        v_partmaxdate := substr(v_current_maxval, 2, 4) || '-' ||
                         substr(v_current_maxval, 6, 2) || '-01';
      elsif length(v_current_maxval) = 12 and
            substr(v_current_maxval, 6, 1) = '-' and
            substr(v_current_maxval, 9, 1) = '-' then
        v_format      := 'YYYY-MM-DD';
        v_partmaxdate := replace(v_current_maxval, '''', '');
      elsif length(v_current_maxval) = 10 and
            instr(v_current_maxval, '-') = 0 then
        v_format      := 'YYYYMMDD';
        v_partmaxdate := substr(v_current_maxval, 2, 4) || '-' ||
                         substr(v_current_maxval, 6, 2) || '-' ||
                         substr(v_current_maxval, 8, 2);
      end if;
      if length(v_current_minval) = 9 and
         substr(v_current_minval, 6, 1) = '-' then
        v_partmindate := REPLACE(v_current_minval, '''', NULL) || '-01';
      elsif length(v_current_minval) = 8 and
            instr(v_current_minval, '-') = 0 then
        v_partmindate := substr(v_current_minval, 2, 4) || '-' ||
                         substr(v_current_minval, 6, 2) || '-01';
      elsif length(v_current_minval) = 12 and
            substr(v_current_minval, 6, 1) = '-' and
            substr(v_current_minval, 9, 1) = '-' then
        v_partmindate := replace(v_current_minval, '''', '');
      elsif length(v_current_minval) = 10 and
            instr(v_current_minval, '-') = 0 then
        v_partmindate := substr(v_current_minval, 2, 4) || '-' ||
                         substr(v_current_minval, 6, 2) || '-' ||
                         substr(v_current_minval, 8, 2);
      end if;
      if length(v_current_2stval) = 9 and
         substr(v_current_2stval, 6, 1) = '-' then
        v_part2stdate := REPLACE(v_current_2stval, '''', NULL) || '-01';
      elsif length(v_current_2stval) = 8 and
            instr(v_current_2stval, '-') = 0 then
        v_part2stdate := substr(v_current_2stval, 2, 4) || '-' ||
                         substr(v_current_2stval, 6, 2) || '-01';
      elsif length(v_current_2stval) = 12 and
            substr(v_current_2stval, 6, 1) = '-' and
            substr(v_current_2stval, 9, 1) = '-' then
        v_part2stdate := replace(v_current_2stval, '''', '');
      elsif length(v_current_2stval) = 10 and
            instr(v_current_2stval, '-') = 0 then
        v_part2stdate := substr(v_current_2stval, 2, 4) || '-' ||
                         substr(v_current_2stval, 6, 2) || '-' ||
                         substr(v_current_2stval, 8, 2);
      end if;
    end if;
    v_part_type := null;
    if v_partmaxdate is not null and v_part2stdate is not null then
      if to_date(v_partmaxdate, 'yyyy-mm-dd') =
         add_months(TO_DATE(v_part2stdate, 'YYYY-MM-DD'), 1) THEN
        v_part_type := 'MONTH';
      elsif to_date(v_partmaxdate, 'yyyy-mm-dd') =
            TO_DATE(v_part2stdate, 'YYYY-MM-DD') + 1 then
        v_part_type := 'DAY';
      elsif to_date(v_partmaxdate, 'yyyy-mm-dd') =
            TO_DATE(v_part2stdate, 'YYYY-MM-DD') + 7 then
        v_part_type := 'WEEK';
      elsif to_date(v_partmaxdate, 'yyyy-mm-dd') -
            TO_DATE(v_part2stdate, 'YYYY-MM-DD') in (8, 10, 11) then
        v_part_type := 'TEN';
      elsif to_date(v_partmaxdate, 'yyyy-mm-dd') =
            add_months(TO_DATE(v_part2stdate, 'YYYY-MM-DD'), 1) then
        v_part_type := 'YEAR';
      elsif to_date(v_partmaxdate, 'yyyy-mm-dd') -
            TO_DATE(v_part2stdate, 'YYYY-MM-DD') in (5,6) then
           v_part_type := 'FIVE';
      else
        v_part_type := to_date(v_partmaxdate, 'yyyy-mm-dd') -
                       TO_DATE(v_part2stdate, 'YYYY-MM-DD');
      end if;
    end if;
    insert into dbamon.tBL_part_Info
    values
      (v_table_owner,
       v_table_name,
       v_minpart,
       v_maxpart,
       v_partmindate,
       v_partmaxdate,
       v_current_minval,
       v_current_maxval,
       v_partcol_type,
       sysdate,
       v_isdefault,
       v_format,
       v_part_type,
       v_gi_count,
       v_partcol_name,
       v_interval);
    commit;
  end GATHER_TABLE_INFO;
  PROCEDURE GATHER_PARTITION_INFO AS
  begin
    delete dbamon.tbl_part_info;
    commit;
    for rm in (select *
                 from DBA_PART_TABLES t
                WHERE T.OWNER NOT IN ('SYS', 'SYSTEM')
                  and t.partitioning_type = 'RANGE'
                  and t.table_name not like 'BIN$%') loop
      GATHER_table_INFO(rm.owner, rm.table_name);
    end loop;
  end GATHER_PARTITION_INFO;
  PROCEDURE ADD_ALL_PART AS
    PROC_NAME VARCHAR2(100);
    ERRMSG    VARCHAR2(100);
  BEGIN
    PROC_NAME := 'STP_ADD_DAY_DT';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_ADD_DAY_DT;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_DAY_VAR';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_ADD_DAY_VAR;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    PROC_NAME := 'STP_ADD_FIVE_DT';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_FIVE_DT;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_FIVE_VAR';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_FIVE_VAR;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_WEEK_DT';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_WEEK_DT;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_WEEK_VAR';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_WEEK_VAR;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_TEN_DT';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_TEN_DT;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_TEN_VAR';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_TEN_VAR;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_MON_DT';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    STP_ADD_MON_DT;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_ADD_MON_VAR';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_ADD_MON_VAR;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
  EXCEPTION
    WHEN OTHERS THEN
      ERRMSG := SUBSTR(SQLERRM, 1, 100);
      INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, ERRMSG, SYSDATE);
  END ADD_ALL_PART;
  PROCEDURE DEL_ALL_PART AS
    PROC_NAME VARCHAR2(100);
    ERRMSG    VARCHAR2(100);
  BEGIN
    PROC_NAME := 'STP_DEL_DAY';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_DEL_DAY;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_DEL_TEN';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_DEL_TEN;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_DEL_WEEK';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_DEL_WEEK;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
    PROC_NAME := 'STP_DEL_MON';
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'START', SYSDATE);
    COMMIT;
    STP_DEL_MON;
    INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, 'END', SYSDATE);
    COMMIT;
  EXCEPTION
    WHEN OTHERS THEN
      ERRMSG := SUBSTR(SQLERRM, 1, 100);
      INSERT INTO TBL_PART_ERR VALUES (PROC_NAME, ERRMSG, SYSDATE);
  END DEL_ALL_PART;
end PKG_MAINTEN_PART;



create or replace procedure dbamon.config_tab_policy(
                                              v_MSG            OUT VARCHAR2, ---------信息反馈。
v_table_owner     in varchar2, ------分区表属主
                                              v_table_name      in varchar2, ------分区表名字
                                              v_drop_time_units in number, ----保留分区个数
                                              v_policy          in number, ------1 加删,2不加不删,3,只加不删,4 只删不加。
                                              v_start_time      in number default 0, -----开始维护时间(24小时制,0-23)
                                              v_end_time        in number default 24, ----结束维护时间 (24小时制,1-24)
                                              v_partition_type in varchar2 default null, ----分区类型,支持WEEK,MONTH,DAY,FIVE,TEN
                                              v_tab_tbs        IN VARCHAR2 DEFAULT NULL, -----表所在表空间,可以为空
                                              v_INX_TBS        IN VARCHAR2 DEFAULT NULL ------索引所在表空间,可以为空,

                                              ) as
  l_count                 number;
  l_table_owner           varchar2(40);
  l_table_name            varchar2(40);
  l_partition_column_type varchar2(30);
  l_partition_type        varchar2(100);
  l_format                varchar2(20);
  l_maxpartition          varchar2(100);
  l_gl_idx                number(3);
  l_auto                  varchar2(30);
  l_add_time_units        number(5);
  apperr exception;
begin
  l_table_owner := upper(v_TABLE_OWNER);
  l_table_name  := upper(v_TABLE_NAME);
  -----判断输入是否符合规范
  --判断是否RANGE分区表
  select count(*)
    into l_count
    from dba_part_tables t
   where t.owner = l_table_owner
     and t.table_name = l_table_name
     and partitioning_type = 'RANGE';
   v_msg:='OK';
  if l_count = 0 then
    v_MSG := '配置失败:表不是分区表或者不是RANGE类型分区';
    raise apperr;
  end if;
  if v_start_time not in (0,
                          1,
                          2,
                          3,
                          4,
                          5,
                          6,
                          7,
                          8,
                          9,
                          10,
                          11,
                          12,
                          13,
                          14,
                          15,
                          16,
                          17,
                          18,
                          19,
                          20,
                          21,
                          22,
                          23) or
     v_end_time not in (1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13,
                        14,
                        15,
                        16,
                        17,
                        18,
                        19,
                        20,
                        21,
                        22,
                        23,
                        24) then
    v_msg := '配置失败:开始时间应该为0-23之间的整数, 结束时间应该为1-24之间整数';
    raise apperr;
  end if;
  if v_policy not in (1, 2, 3, 4) then
    v_msg := '配置失败:policy 参数只能为1,2,3,4, 1 加删,2不加不删,3,只加不删,4 只删不加';
    raise apperr;
  end if;
  if upper(v_partition_type) not in ('WEEK', 'DAY', 'TEN', 'MONTH', 'FIVE') and
     v_partition_type is not null then
    v_msg := '配置失败, 分区类型只可以为WEEK,DAY,TEN,MONTH,FIVE';
    raise apperr;
  end if;
  ---开始收集信息
  dbamon.pkg_mainten_part.gather_table_info(l_table_owner, l_table_name);
  select count(*)
    into l_count
    from dbamon.tbl_part_info
   where table_owner = v_table_owner
     and table_name = v_table_name;
  if l_count = 0 then
    v_msg := '配置失败:无法获取分区表信息,联系DBA';
    raise apperr;
  end if;
  select partition_column_type,
         partition_type,
         format,
         autointerval,
         max_partition,
         global_indx
    into l_partition_column_type,
         l_partition_type,
         l_format,
         l_auto,
         l_maxpartition,
         l_gl_idx
    from dbamon.tbl_part_info
   where table_owner = v_table_owner
     and table_name = v_table_name;
  if l_partition_column_type like 'TIMESTAMP%' then
    l_partition_column_type := 'DATE';
  elsif l_partition_column_type in ('CHAR', 'VARCHAR') then
    l_partition_column_type := 'VARCHAR2';
  end if;
  if l_partition_column_type not in ('DATE', 'TIMESTAMP', 'VARCHAR2') then
    v_msg := '配置失败: 分区列数据类型只可以为DATE,TIMESTAMP,VARCHAR2,CHAR,VARCHAR 类型';
    raise apperr;
  end if;
  if upper(v_partition_type) in ('WEEK', 'DAY', 'TEN', 'MONTH', 'FIVE') then
    l_partition_type := upper(v_partition_type);
  end if;
  if l_partition_type = 'WEEK' then
    l_add_time_units := 12;
  elsif l_partition_type = 'MONTH' then
    l_add_time_units := 3;
  elsif l_partition_type = 'DAY' then
    l_add_time_units := 16;
  elsif l_partition_type in ('FIVE', 'TEN') then
    l_add_time_units := 10;
  end if;
  if l_auto is not null and v_policy in (1, 3) then
    v_msg := '配置失败: 11g 自增长分区,不可以配置成1 加删,3,只加不删';
    raise apperr;
  end if;
  delete dbamon.tbl_tab_part_config
   where table_owner = l_table_owner
     and table_name = l_table_name;
  insert into dbamon.tbl_tab_part_config
    (id,
     table_owner,
     table_name,
     partition_column_type,
     partition_pre,
     partition_type,
     drop_time_units,
     add_time_units,
     tablespace_name,
     index_tb_name,
     valid_flg,
     config_type,
     format,
     shour,
     ehour)
  values
    (dbamon.SEQ_TM_PART_MAINTEN.NEXTVAL,
     l_table_owner,
     l_table_name,
     l_partition_column_type,
     NVL(SUBSTR(l_maxpartition, 1, INSTR(l_maxpartition, '2') - 1), 'PART'),
     l_partition_type,
     v_drop_time_units,
     l_add_time_units,
     v_tab_tbs,
     v_INX_TBS,
     v_policy,
     'RUN',
     l_format,
     v_start_time,
     v_end_time);
    insert into dbamon.tbl_config_log
      (config_time,
       username,
       oseruser,
       proxy_user,
       ip_addr,
       machine,
       table_owner,
       table_name,
       drop_time_units,
       policy,
       v_start_time,
       v_end_time,
       v_partition_type,
       v_tab_tbs,
       v_inx_tbs,
       config_result)
    values
      (sysdate,
       SYS_CONTEXT('USERENV', 'CURRENT_USER'),
       SYS_CONTEXT('USERENV', 'OS_USER'),
        SYS_CONTEXT('USERENV', 'PROXY_USER'),
        SYS_CONTEXT('USERENV', 'IP_ADDRESS'),
       SYS_CONTEXT('USERENV', 'TERMINAL') ,
       v_table_owner,
       v_table_name,
       v_drop_time_units,
       v_policy,
       v_start_time,
       v_end_time,
       v_partition_type,
       v_tab_tbs,
       v_inx_tbs,
       v_msg);
       commit;
exception
  when apperr then
    dbms_output.put_line(v_msg);
    insert into dbamon.tbl_config_log
      (config_time,
       username,
       oseruser,
       proxy_user,
       ip_addr,
       machine,
       table_owner,
       table_name,
       drop_time_units,
       policy,
       v_start_time,
       v_end_time,
       v_partition_type,
       v_tab_tbs,
       v_inx_tbs,
       config_result)
    values
      (sysdate,
       SYS_CONTEXT('USERENV', 'CURRENT_USER'),
       SYS_CONTEXT('USERENV', 'OS_USER'),
        SYS_CONTEXT('USERENV', 'PROXY_USER'),
        SYS_CONTEXT('USERENV', 'IP_ADDRESS'),
       SYS_CONTEXT('USERENV', 'TERMINAL') ,
       v_table_owner,
       v_table_name,
       v_drop_time_units,
       v_policy,
       v_start_time,
       v_end_time,
       v_partition_type,
       v_tab_tbs,
       v_inx_tbs,
       v_msg);
      commit;
  when others then
    v_msg := substr(sqlerrm, 1, 50);
    insert into dbamon.tbl_config_log
      (config_time,
       username,
       oseruser,
       proxy_user,
       ip_addr,
       machine,
       table_owner,
       table_name,
       drop_time_units,
       policy,
       v_start_time,
       v_end_time,
       v_partition_type,
       v_tab_tbs,
       v_inx_tbs,
       config_result)
    values
      (sysdate,
       SYS_CONTEXT('USERENV', 'CURRENT_USER'),
       SYS_CONTEXT('USERENV', 'OS_USER'),
        SYS_CONTEXT('USERENV', 'PROXY_USER'),
        SYS_CONTEXT('USERENV', 'IP_ADDRESS'),
       SYS_CONTEXT('USERENV', 'TERMINAL') ,
       v_table_owner,
       v_table_name,
       v_drop_time_units,
       v_policy,
       v_start_time,
       v_end_time,
       v_partition_type,
       v_tab_tbs,
       v_inx_tbs,
       v_msg);
      commit;
end;


grant select on DBAMON.TBL_PART_INFO to bspdev;
grant select on DBAMON.TBL_PART_INFO to PUBLIC;
grant select on DBAMON.TBL_TAB_PART_CONFIG to bspdev;
grant select on DBAMON.TBL_PART_MANAGE_SQL to PUBLIC;
grant select on DBAMON.TBL_PART_MANAGE_SQL to bspdev;
grant select on DBAMON.TBL_PART_MANAGE_SQL to PUBLIC;
grant select on DBAMON.TBL_PART_ERR to PUBLIC;
grant select on DBAMON.TBL_PART_ERR to bspdev;
grant select on DBAMON.TBL_CONFIG_LOG to PUBLIC;
grant select on DBAMON.TBL_CONFIG_LOG to bspdev;

grant execute on DBAMON.config_tab_policy TO PUBLIC;
grant select_catalog_role to dbamon;


--dbmon
declare
v_job number;
begin
sys.dbms_job.submit(
job => v_job,
what=> 'pkg_mainten_part.ADD_ALL_PART();
pkg_mainten_part.del_ALL_PART();',
next_date=>sysdate,
interval =>'sysdate+1/24');
commit;
end;

  

posted @ 2016-09-18 17:50  lwx64397  阅读(350)  评论(0编辑  收藏  举报