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
网上找来的资料,稍有调整