MySQL自动添加分区表的函数

sql 复制代码
DROP PROCEDURE IF EXISTS append_partition_table; 
  
CREATE PROCEDURE `append_partition_table`( 
  in databasename varchar(50), 
  in partition_tablename varchar(50), 
  in end_date datetime, 
  in partitiontype int, 
  in gaps int) 
L_END: 
BEGIN 
  -- 功能:为指定数据库中的指定表,按天、按月、按年添加分区子表,不是按天时,添加的分区子表会比[截止日期]稍大些日期 
  -- 注意:使用该存储过程必须保证相应数据库表中至少有一个手动分区 
  -- Demo1:call append_partition_table('hwg_db', 'queue_main', '2021-10-19', 0, 1); 
  -- Demo2:call append_partition_table('hwg_db', 'queue_main2', '2021-11-19', 1, 1); 

-- 参数:databasename:创建分区的数据库 
-- 参数:partition_tablename:创建分区的表的名称 
-- 参数:partition_number:一次创建多少个分区 
-- 参数:end_date:创建分区表的截止日期 
-- 参数:partitiontype:分区类型[0按天分区,1按月分区,2按年分区] 
-- 参数:gaps:分区间隔,如果分区类型为0则表示每个分区的间隔为 gaps天; 
--            如果分区类型为1则表示每个分区的间隔为 gaps月 
--            如果分区类型为2则表示每个分区的间隔为 gaps年 
  
   -- 最大一个[分区描述的值] 
   DECLARE max_partition_description varchar(255) DEFAULT ''; 
   -- 分区子表的表名 
   DECLARE p_name varchar(255) DEFAULT ''; 
   -- 用于存储待创建分区表的日期值,会处理后变成分区子表的分区依据/分区描述/分区字段的值 
   DECLARE p_description varchar(255) DEFAULT ''; 
   -- 判断是否已手动分区 
   DECLARE isexist_partition varchar(255) DEFAULT ''; 
   -- 循环递增变量i 
   DECLARE i int DEFAULT 1; 
   -- 已建分区表的最大描述值,对应的日期,用于判断是否可以退出循环 
   DECLARE partition_max_date datetime;
   -- 用于存储SQL语句 
   DECLARE sql_stmt TEXT;

-- partitiontype 只接收0/1/2三种值 
  IF partitiontype not in (0,1,2) THEN 
    SELECT "The Parameter [Partitiontype] is incorrect. Only 0, 1, and 2 are supported!!! " AS "ERROR"; 
    LEAVE L_END; 
  END IF; 

  SET partition_tablename = LOWER(partition_tablename); 
  -- 查看对应数据库对应表是否已经有手动分区 [自动分区前提是必须有手动分区] 
  SELECT partition_name INTO isexist_partition 
    FROM information_schema.partitions 
    WHERE table_schema = databasename AND table_name = partition_tablename LIMIT 1; 
  -- 如果不存在则打印错误并退出存储过程 
  IF isexist_partition IS NULL OR isexist_partition = '' THEN 
    SELECT "partition table not is exist" AS "ERROR"; 
    LEAVE L_EMD; 
  END IF; 

  -- 获取最大[降序获取]的分区描述[值], 即当前分区字段的最大值/最大日期 
  SELECT partition_description INTO max_partition_description 
    FROM information_schema.partitions 
   WHERE table_schema = databasename AND table_name = partition_tablename 
   ORDER BY partition_description DESC LIMIT 1; 

  -- 如果最大分区没有,说明没有手动分区,则无法创建自动分区 
  IF max_partition_description IS NULL OR max_partition_description = '' THEN 
    SELECT "partition table is error, not found max_partition" AS "ERROR"; 
    LEAVE L_END; 
  END IF; 
  SET partition_max_date = FROM_DAYS(max_partition_description); 

  -- 打印max_partition_description变量 
  -- select CONCAT("max_partition_description=", max_partition_description); 

  -- 替换前后的单引号[''两个引号表示一个单引号的转义]
  SET max_partition_description = REPLACE(CAST(max_partition_description AS CHAR), '''', ''); 
  -- 开始循环,自动分区 
  WHILE (partition_max_date <= end_date) DO 
    IF (partitiontype = 0) THEN 
      -- 每个分区按天递增, 递增gaps天, 得到新的日期p_description 
      SET p_description = DATE_ADD(FROM_DAYS(max_partition_description), INTERVAL i*gaps DAY); 
    ELSEIF (partitiontype = 1) THEN 
      -- 每个分区按月递增, 递增gaps月, 得到新的日期p_description, PS,需使用LAST_DAY()取当月最后一天 
      SET p_description = LAST_DAY(DATE_ADD(FROM_DAYS(max_partition_description), INTERVAL i*gaps MONTH)); 
    ELSE 
      -- 每个分区按年递增, 递增gaps年, 得到新的日期p_description, 强行通过year()函数取[年],然后拼接得到一年最后一天 
      SET p_description = CONCAT(YEAR(DATE_ADD(FROM_DAYS(max_partition_description), INTERVAL i*gaps YEAR)), '-12-31'); 
    END IF; 
    -- 打印p_description变量 
    -- select CONCAT("p_description=", p_description); 
    
    -- 删除空格 
    SET p_name = REPLACE(p_description, ' ', ''); 
    -- 例如2020.10.20的记录实际是less than 2020.10.21 
    SET p_description = DATE_ADD(p_description, INTERVAL 1 DAY); 
    -- 如果有横杆替换为空 
    SET p_name = REPLACE(p_name, '-', ''); 
    -- 删除时间冒号 
    SET p_name = REPLACE(p_name, ':', ''); 
    -- 删除时间分号 
    SET p_name = REPLACE(p_name, '-', ''); 
     
    -- 检查分区是否已经存在
    SET @check_sql = CONCAT('SELECT COUNT(*) INTO @partition_exists FROM information_schema.partitions ',
                           'WHERE table_schema = ''', databasename, ''' AND table_name = ''', partition_tablename, ''' ',
                           'AND partition_name = ''p', p_name, '''');
    
    PREPARE check_stmt FROM @check_sql;
    EXECUTE check_stmt;
    DEALLOCATE PREPARE check_stmt;
    
    -- 只有当分区不存在时才创建
    IF @partition_exists = 0 THEN
      -- 注意:表名里的日期比分区的日期,小1天!!! 
      -- alter table tablename add partition ( partition p20190521 values less than ('2019-05-22 23:59:59') ); 
      SET @sql = CONCAT('ALTER TABLE ', partition_tablename, 
               ' ADD PARTITION ( PARTITION p', p_name, ' VALUES LESS THAN (TO_DAYS(\'', p_description, 
               '\')) COMMENT = \' LESS THAN ', p_description, '\')'); 
     
      -- 打印sql变量 
      -- SELECT @sql; 
     
      -- 准备sql语句 
      PREPARE stmt FROM @sql; 
      -- 执行sql语句 
      EXECUTE stmt; 
      -- 释放资源 
      DEALLOCATE PREPARE stmt; 
    END IF;
    
    -- 递增变量 
    SET i = (i + 1) ; 
    -- 更新循环条件中的partition_max_date
    SET partition_max_date = STR_TO_DATE(p_description, "%Y-%m-%d"); 
  END WHILE; 
  
END

网上找来的资料,稍有调整

相关推荐
蜡笔小炘12 小时前
LVS -- 利用防火墙标签(FireWall Mark)解决轮询错误
服务器·数据库·lvs
韩立学长12 小时前
基于Springboot泉州旅游攻略平台d5h5zz02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·旅游
Re.不晚13 小时前
MySQL进阶之战——索引、事务与锁、高可用架构的三重奏
数据库·mysql·架构
老邓计算机毕设13 小时前
SSM智慧社区信息化服务平台4v5hv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·智慧社区、·信息化平台
麦聪聊数据13 小时前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
2301_7903009613 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python
m0_7369191013 小时前
用Pandas处理时间序列数据(Time Series)
jvm·数据库·python
亓才孓13 小时前
[JDBC]PreparedStatement替代Statement
java·数据库
m0_4665252914 小时前
绿盟科技风云卫AI安全能力平台成果重磅发布
大数据·数据库·人工智能·安全
爱学习的阿磊15 小时前
使用Fabric自动化你的部署流程
jvm·数据库·python