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

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

相关推荐
ʚB҉L҉A҉C҉K҉.҉基҉德҉^҉大3 小时前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
哈__3 小时前
多模融合 一体替代:金仓数据库 KingbaseES 重构企业级统一数据基座
数据库·重构
老邓计算机毕设4 小时前
SSM医院病人信息管理系统e7f6b(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·医院信息化·ssm 框架·病人信息管理
2601_949613024 小时前
flutter_for_openharmony家庭药箱管理app实战+药品分类实现
大数据·数据库·flutter
dyyx1115 小时前
使用Scikit-learn进行机器学习模型评估
jvm·数据库·python
踢足球09295 小时前
寒假打卡:2026-01-27
数据库
不想写bug呀5 小时前
MySQL索引介绍
数据库·mysql
weixin_499771555 小时前
使用Seaborn绘制统计图形:更美更简单
jvm·数据库·python
青春男大5 小时前
Redis和RedisTemplate快速上手
java·数据库·redis·后端·spring·缓存
冉冰学姐5 小时前
SSM医院预约挂号管理系统q9ig2(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·毕业设计·医院预约挂号系统·ssm 框架