找回密码
 注册账号

QQ登录

只需一步,快速开始

手机号码,快捷登录

手机号码,快捷登录

初学者课程:T3自学|T6自学|U8自学软件下载课件下载工具下载资料:通资料|U8资料|NC|培训|年结积分规则 | 使用常见问题Q&A
知识库:U8 | | NC | U9 | OA | 政务U8|U9|NCC|NC65|NC65客开|NCC客开新手必读 | 任务 | 快速增金币用友QQ群[微信群]
查看: 431|回复: 4

[转帖] Oracle动态添加分区

[复制链接]
发表于 2023-9-27 16:53:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册账号

×


转贴:Oracle动态添加分区

存储过程:
  1. create or replace procedure manage_table_partitions(
  2.      tname varchar2,
  3.      curDate date
  4. ) is
  5.     IS_PART_EXISTS         integer          := 0;
  6.     IS_TABLE_EXISTS        integer          := 0;
  7.     IS_PART_TABLE          integer          := 0;
  8.     P_LABEL                varchar2(30)     := to_char(curDate,'YYYYMMDD');
  9.     MAX_PARTITION_DATE     date;
  10.     MIN_PARTITION_DATE     date;
  11.     TARGET_TABLE           varchar2(40)     := upper(trim(tname));
  12.     V_SQL                  varchar2(3000)   := '';

  13. -- 定义异常类型变量
  14.     no_table_exception          exception;
  15.     less_than_latest_exception  exception;

  16. -- 固定参数
  17.    ADD_FREQ                integer          := 1;
  18. begin

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

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

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


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

  39.     if IS_PART_EXISTS <> 1 then
  40.    
  41.         -- 查看分区表最大分区和最小分区
  42.         select  
  43.              max(to_date(substr(partition_name,2),'YYYY-MM-DD'))
  44.              ,min(to_date(substr(partition_name,2),'YYYY-MM-DD'))
  45.         into
  46.              MAX_PARTITION_DATE
  47.              ,MIN_PARTITION_DATE
  48.         from user_tab_partitions
  49.         where table_name = TARGET_TABLE
  50.         group by table_name;

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

  56.         dbms_output.put_line('添加分区,按照指定频率添加分区');
  57.         MAX_PARTITION_DATE := MAX_PARTITION_DATE + ADD_FREQ;
  58.         while MAX_PARTITION_DATE <= curDate loop
  59.             begin
  60.                 V_SQL := 'alter table '|| tname || ' add partition P' || to_char(MAX_PARTITION_DATE,'YYYYMMDD') || ' values less than ';
  61.                 V_SQL := V_SQL || '(to_date(''' || to_char(MAX_PARTITION_DATE + ADD_FREQ,'YYYY-MM-DD') ||''',''YYYY-MM-DD''))';
  62.                 --dbms_output.put_line(V_SQL);
  63.                 execute immediate V_SQL;
  64.                 MAX_PARTITION_DATE := MAX_PARTITION_DATE + ADD_FREQ;
  65.             end;
  66.         end loop;
  67.     else
  68.         dbms_output.put_line('清除分区中的数据');
  69.         V_SQL := 'alter table '||tname||' truncate partition P'||P_LABEL;
  70.         dbms_output.put_line(V_SQL);
  71.         execute immediate V_SQL;
  72.     end if;        
  73. end manage_table_partitions;
复制代码


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

存储过程如楼上。
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 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
回复 点赞 拍砖

使用道具 举报

发表于 2023-9-28 13:49:03 | 显示全部楼层
回复 点赞 拍砖

使用道具 举报

发表于 2024-1-12 15:15:29 | 显示全部楼层
回复 点赞 拍砖

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

QQ|站长微信|Archiver|手机版|小黑屋|用友之家 ( 蜀ICP备07505338号|51072502110008 )

GMT+8, 2024-4-27 22:46 , Processed in 0.025027 second(s), 8 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表