zhou66 发表于 2023-9-27 16:53:01

Oracle动态添加分区



转贴:Oracle动态添加分区

存储过程:
create or replace procedure manage_table_partitions(
   tname varchar2,
   curDate date
) is
    IS_PART_EXISTS         integer          := 0;
    IS_TABLE_EXISTS      integer          := 0;
    IS_PART_TABLE          integer          := 0;
    P_LABEL                varchar2(30)   := to_char(curDate,'YYYYMMDD');
    MAX_PARTITION_DATE   date;
    MIN_PARTITION_DATE   date;
    TARGET_TABLE         varchar2(40)   := upper(trim(tname));
    V_SQL                  varchar2(3000)   := '';

-- 定义异常类型变量
    no_table_exception          exception;
    less_than_latest_exceptionexception;

-- 固定参数
   ADD_FREQ                integer          := 1;
begin

    -- 查看这张表是否为分区表
    select count(*) into IS_PART_TABLE from user_part_tables
    where table_name = TARGET_TABLE;

    if IS_PART_TABLE <> 1 then
      select count(*) into IS_TABLE_EXISTS from tab where tname = TARGET_TABLE;
      if IS_TABLE_EXISTS <> 1 then
            dbms_output.put_line(tname||',这张表不存在');
            raise no_table_exception;
      end if;

      dbms_output.put_line(tname||',这张表不是分区表,将直接清空表中数据');
      V_SQL := 'truncate table ' || tname;
      execute immediate V_SQL;
      return ;
    end if;


    -- 查看分区是否存在
    select count(*) into IS_PART_EXISTS
    from user_tab_partitions
    where table_name = TARGET_TABLE
         and partition_name = 'P'||P_LABEL
    ;

    if IS_PART_EXISTS <> 1 then
   
      -- 查看分区表最大分区和最小分区
      select
             max(to_date(substr(partition_name,2),'YYYY-MM-DD'))
             ,min(to_date(substr(partition_name,2),'YYYY-MM-DD'))
      into
             MAX_PARTITION_DATE
             ,MIN_PARTITION_DATE
      from user_tab_partitions
      where table_name = TARGET_TABLE
      group by table_name;

      -- 检查准备创建的分区是否小于当前表中分区最小日期
      if MIN_PARTITION_DATE > curDate then
            dbms_output.put_Line('数据日期已经小于分区表最小日期,请重建表,重新设定最小日期分区');
            raise less_than_latest_exception;
      end if;

      dbms_output.put_line('添加分区,按照指定频率添加分区');
      MAX_PARTITION_DATE := MAX_PARTITION_DATE + ADD_FREQ;
      while MAX_PARTITION_DATE <= curDate loop
            begin
                V_SQL := 'alter table '|| tname || ' add partition P' || to_char(MAX_PARTITION_DATE,'YYYYMMDD') || ' values less than ';
                V_SQL := V_SQL || '(to_date(''' || to_char(MAX_PARTITION_DATE + ADD_FREQ,'YYYY-MM-DD') ||''',''YYYY-MM-DD''))';
                --dbms_output.put_line(V_SQL);
                execute immediate V_SQL;
                MAX_PARTITION_DATE := MAX_PARTITION_DATE + ADD_FREQ;
            end;
      end loop;
    else
      dbms_output.put_line('清除分区中的数据');
      V_SQL := 'alter table '||tname||' truncate partition P'||P_LABEL;
      dbms_output.put_line(V_SQL);
      execute immediate V_SQL;
    end if;      
end manage_table_partitions;


zhou66 发表于 2023-9-27 16:54:23

在数据处理过程中,通常对于数据比较大的表进行分区管理,而分区的依据往往是数据日期,每一天或者每几天数据存储在一个指定的分区中,当数据量一天天增加后,通过分区进行过滤,有利于快速查询某一天的数据。
在向分区表中插入数据时,分区表必须有能够装载这条数据的分区,比如将2018-01-08的数据全部放在P20180102这个分区,而这个分区条件是数据日期小于等于2018-01-02,那么这条数据日期为2018-01-08的数据就无法insert到这张表,这样就会出现错误。
为了解决为分区表自动扩展分区的需求,我们编写了一个存储过程,用来在向表中insert数据时,动态的对表进行添加分区或清除分区。只需要在insert之前,执行下边存储过程即可。

存储过程如楼上。

zhou66 发表于 2023-9-27 17:19:22

(1)
numtoyminterval (<x>,<c>)

将 x 转为 interval year to month 数据类型。

常用的单位有 ('year','month')。

测试一下:

select sysdate, sysdate + numtoyminterval(3, 'year') as res from dual;

(2)
numtodsinterval(<x>,<c>) ,x 是一个数字,c 是一个字符串。

把 x 转为 interval day to second 数据类型。

常用的单位有 ('day','hour','minute','second')。

测试一下:

select sysdate, sysdate + numtodsinterval(4,'hour') as res from dual;
————————————————
版权声明:本文为CSDN博主「力哥讲技术」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37723088/article/details/129472436

Marco-1988 发表于 2023-9-28 13:49:03

感谢分享!!

abjun 发表于 2024-1-12 15:15:29

感谢分享!!
页: [1]
查看完整版本: Oracle动态添加分区