关于oracle 11g自动分区+分区改名+定时任务综合使用实现自动分区后可以进行分区查询

一直想用oracle 11g 的interval分区(间断分区),这需要配合分区改名才能让我们可以使用分区查询,因为自动分区出来的分区名会是SYSPxxx这样。。

下面直接代码

drop tablespace bank_data including contents and datafiles;


create tablespace bank_data  
logging  
datafile 'D:\bank.dbf' 
size 512m  
autoextend on  
next 512m maxsize 2048m  
extent management local; 


drop sequence seq_topic;


alter table topic drop constraint ck_topic_classify;
alter table bank drop constraint ck_bank_subject;
alter table bank drop constraint ck_bank_status;


drop table topic purge;
drop table bank purge;


create table bank(
   id varchar2(17) primary key,
   district varchar2(30) not null,
   subject number(1) default 1 not null constraint ck_bank_subject check(subject in(1,4)),
   status number(1) default 0 not null constraint ck_bank_status check(status in(0,1)),
   remark varchar2(300)
);


--1道路交通安全法律、法规和规章 2交通信号 3安全行车、文明驾驶基础知识 4机动车驾驶操作相关基础知识
--1违法行为综合判断与案例分析 2安全行车常识 3常见交通标志、标线和交通手势辨识 4驾驶职业道德和文明驾驶常识
--5恶劣气候和复杂道路条件下驾驶常识 6紧急情况下避险常识 7交通事故救护及常见危化品处理常识
create table topic(
   tid number(6) primary key,
   version varchar2(17) not null,
   pubdate date not null,
   classify number(2) default 11 not null constraint ck_topic_classify check(classify in(11,12,13,14,41,42,43,44,45,46,47)),
   title varchar2(1500) not null,
   answer varchar2(20) not null,
   explain varchar2(1200),
   image varchar2(30)
)
partition by range(pubdate)
interval (NUMTOYMINTERVAL (3, 'MONTH')) store in (bank_data)
subpartition by list(classify)
subpartition template(
  subpartition s1 values (11,12,13,14),
  subpartition s4 values (default)
)
(partition p_201604 values less than (TO_DATE ('04/01/2016', 'MM/DD/YYYY')) tablespace bank_data);




alter table topic add constraint fk_topic_bank_version foreign key(version) references bank(id);


create sequence seq_topic start with 100000 minvalue 100000;




--修改分区名存储过程
create or replace procedure pro_partition
as
 v_sql varchar(400);
 v_table_name user_tab_partitions.table_name%type;
 v_partition_name user_tab_partitions.partition_name%type;
 v_high_value varchar(200);
 v_tmp_partition_name user_tab_partitions.partition_name%type;
 cursor cur1 is
   select
      table_name ,
      partition_name ,
      high_value 
    from user_tab_partitions 
    where partition_name like 'SYS%' and table_name='TOPIC';
begin
  open cur1;
  loop
    fetch cur1 into v_table_name,v_partition_name,v_high_value;
    exit when cur1%notfound;
    v_tmp_partition_name := substr(v_high_value,11,10);
    v_tmp_partition_name := to_char( to_date(v_tmp_partition_name,'yyyy-mm-dd') , 'yyyymm');
    v_sql := 'alter table '||v_table_name||' rename partition '
      ||v_partition_name
      ||' to P_'||v_tmp_partition_name;
    execute immediate v_sql;
  end loop;
  close cur1;
end;
/
--修改子分区名存储过程
--14数字是从select high_value_length from user_tab_subpartitions where subpartition_name='P_201604_S1' and table_name='TOPIC'得来; 
create or replace procedure pro_subpartition
as
 v_sql varchar(400);
 v_table_name user_tab_subpartitions.table_name%type;
 v_partition_name user_tab_subpartitions.partition_name%type;
 v_subpartition_name user_tab_subpartitions.subpartition_name%type;
 v_tmp_subpartition_name user_tab_subpartitions.subpartition_name%type;
 v_temp number;
 cursor cur2 is
   select
      table_name ,
      partition_name ,
      subpartition_name 
    from user_tab_subpartitions 
    where subpartition_name like 'SYS%' and table_name='TOPIC';
begin
  open cur2;
  loop
    fetch cur2 into v_table_name,v_partition_name,v_subpartition_name;
    exit when cur2%notfound;
    select high_value_length into v_temp from user_tab_subpartitions where subpartition_name=v_subpartition_name and table_name='TOPIC';
    if (v_temp=14) then 
    v_tmp_subpartition_name := v_partition_name||'_S1';
    else
    v_tmp_subpartition_name := v_partition_name||'_S4';
    end if;
    v_sql := 'alter table '||v_table_name||' rename subpartition '
      ||v_subpartition_name
      ||' to '||v_tmp_subpartition_name;
    execute immediate v_sql;
  end loop;
  close cur2;
end;
/
--自动分区+改名 分区名格式为P_201604_S1
create or replace procedure pro_job
as
begin
insert into bank values('1','a',1,1,'a');
insert into topic values(1,'1',add_months(sysdate,3),11,'a','a','a','a');
insert into topic values(2,'1',add_months(sysdate,3),41,'a','a','a','a');
pro_partition;
pro_subpartition;
delete from topic where tid in(1,2);
delete from bank where id='1';
end;
/
--删除数据任务
create or replace procedure pro_del
as
v_sql varchar(300);
v_temp varchar(30);
v_num number;
v_date date;
v_count number;
v_partition_name user_tab_partitions.partition_name%type;
begin
select add_months(sysdate,-12) into v_date from dual;
v_num:=to_number(to_char(sysdate,'mm'));
if (v_num<4) then 
v_temp:='04';
elsif (v_num<7) then
v_temp:='07';
elsif (v_num<10) then 
v_temp:='10';
else
v_temp:='01';
end if;
v_partition_name:='P_'||to_char(v_date,'yyyy')||v_temp;
dbms_output.put_line('partition_name====>'||v_partition_name );
select count(1) into v_count from user_tab_partitions where partition_name=v_partition_name and table_name='TOPIC';
if (v_count=1) then 
v_sql:='alter table topic drop partition '||v_partition_name;
execute immediate v_sql;
end if;
end;
/


--定义一个job每个季度第一天凌晨执行自动建表分区
create or replace procedure pro_auto_job
as
v_job number;
begin
execute immediate 'alter table topic deallocate UNUSED KEEP 0';
dbms_job.submit(v_job,'pro_job;',sysdate,'TRUNC(ADD_MONTHS(SYSDATE,3),''q'')');
dbms_job.run(v_job);
end;
/


exec pro_auto_job;


create or replace procedure pro_auto_del
as
job number;
begin
execute immediate 'alter table topic deallocate UNUSED KEEP 0';
dbms_job.submit(job,'pro_del;',sysdate,'TRUNC(ADD_MONTHS(SYSDATE,12),''q'')');
dbms_job.run(job);
end;
/


exec pro_auto_del;


--topic按类型进行分页
create or replace procedure pro_page_topic(v_classify number,v_pageIndex number,v_pageSize number,v_total OUT number,v_cursor OUT sys_refcursor)
as
v_version number(30);
v_partition varchar2(100);
v_year number(20);
v_month number(20);
v_sql varchar2(400);
begin
select max(to_number(id)) into v_version from bank where district='湖南' and subject=to_number(substr(v_classify,0,1)) and status=1 ;
if (v_version is not null) then 
  v_month:=to_number(substr(v_version,5,2));
  v_year:=to_number(substr(v_version,1,4));
  if (v_month<4) then
  v_partition:='P_'||substr(v_version,1,4)||'04_S'||substr(v_classify,0,1);
  elsif (v_month<7) then
  v_partition:='P_'||substr(v_version,1,4)||'07_S'||substr(v_classify,0,1);
  elsif (v_month<10) then
  v_partition:='P_'||substr(v_version,1,4)||'10_S'||substr(v_classify,0,1);
  else
  v_partition:='P_'||to_char(v_year+1)||'01_S'||substr(v_classify,0,1);
  end if;
  v_sql:='select count(1) from topic subpartition ('||v_partition||') where version='||to_char(v_version)||' and classify='||v_classify;
  execute immediate v_sql into v_total;
  v_sql:='select * from ( select a.*,rownum rn from ( select title,answer,explain,image from topic subpartition ('||v_partition||')where version='||to_char(v_version)||' and classify='||v_classify||' ) a where rownum <=('||v_pageIndex||'+1)*'||v_pageSize||' ) where rn>'||v_pageIndex||'*'||v_pageSize;
  open v_cursor for v_sql;
end if;
end;
/


--随机从topic取100个数据
create or replace procedure pro_exam(v_classify number,v_cursor OUT sys_refcursor)
as
v_version number(30);
v_partition varchar2(100);
v_year number(20);
v_month number(20);
v_sql varchar2(400);
begin
select max(to_number(id)) into v_version from bank where district='湖南' and subject=to_number(substr(v_classify,0,1)) and status=1 ;
if (v_version is not null) then 
  v_month:=to_number(substr(v_version,5,2));
  v_year:=to_number(substr(v_version,1,4));
  if (v_month<4) then
  v_partition:='P_'||substr(v_version,1,4)||'04_S'||substr(v_classify,0,1);
  elsif (v_month<7) then
  v_partition:='P_'||substr(v_version,1,4)||'07_S'||substr(v_classify,0,1);
  elsif (v_month<10) then
  v_partition:='P_'||substr(v_version,1,4)||'10_S'||substr(v_classify,0,1);
  else
  v_partition:='P_'||to_char(v_year+1)||'01_S'||substr(v_classify,0,1);
  end if;
  v_sql:='select * from (select title,answer,explain,image from topic subpartition('||v_partition||') where version='||to_char(v_version)||' order by dbms_random.value) where rownum<101';
  open v_cursor for v_sql;
end if;
end;
/


commit;
select partition_name,
  subpartition_name
from user_tab_subpartitions 
where table_name='TOPIC';

关于oracle 11g自动分区+分区改名+定时任务综合使用实现自动分区后可以进行分区查询_第1张图片


总结一下:修改分区依据是high_value,存储过程的分区查询和分页查询都是动态查询,需要先写sql字符串,然后再执行sql字符串,写到这里大家会发现其实压根就不需要用interval分区,直接用存储过程新建分区会更简洁些,不过既然有interval分区,在这就用一下。对于初学者来说,看pl/sql语言会有点畏惧,我刚接触时也是一样,会觉得它很难看懂,其实不是,如果有上面这种情况,可以分开几天来看pl/sql代码,这样连续看同样脚本两三天就发现自己可以接受pl/sql了,以上纯个人建议。。。

你可能感兴趣的:(oracle)