MySQL存储过程代码记录,实现数据表切分和表数据字段的替换

功能:对overnight_abcd根据column01字段的数据进行表切分,且分为overnight_2019、overnight_2018、overnight_2017、overnight_2016、overnight_2015表,同时替换overnight_abcd表中column03字段对应的行政区划代码为对应的中文名,接着,根据column01数据的值,将数据对应存入以'overnight_'开头+数据值的表。

用到的代码:存储过程创建和删除游标循环、Insert into Table2(field1,field2,...) select value1,value2,... from Table1批量查询插入语句(去重复判断)、字符串的分割、UPDATE table SET field = replace(field,'被替换','替换成') 批量替换、create table动态建表CONCAT字符串拼接。

表名和表数据:

1、overnight_abcd。

2、original_et

3、original_etfield

4、original_fielddef

5、rule_valuereplacedetail

代码部分:

delimiter //

drop procedure if exists cutTable //
create procedure cutTable(in oldTable varchar(32), in newTable varchar(32), in cutKey varchar(16), in cutValue varchar(50), in colList varchar(200), in repeatSQL varchar(1000))
comment '执行表切分'
begin

set @cols = substr(colList,1,length(colList)-1);
/* 判断重复 */
/*
INSERT INTO overnight_2019 (
	column01,
	column02,
	column03,
	column04,
	column05
) SELECT
	column01,
	column02,
	column03,
	column04,
	column05
FROM
	overnight_abcd
WHERE
	NOT EXISTS (
		SELECT
			1
		FROM
			overnight_2019
		WHERE
			overnight_abcd.column01 = overnight_2019.column01
		AND overnight_abcd.column02 = overnight_2019.column02
		AND overnight_abcd.column03 = overnight_2019.column03
		AND overnight_abcd.column04 = overnight_2019.column04
		AND overnight_abcd.column05 = overnight_2019.column05
	)
AND column01 = '2019';
*/
set @repeatSQL = CONCAT(' not exists ( select 1 from ', newTable, ' where ', @repeatSQL, ' ) and ');
set @insertSQL = CONCAT('Insert into ', newTable, ' ( ', @cols , ' ) ', 'select ' , @cols, ' from ', oldTable, ' where ', @repeatSQL, cutKey, " = '", cutValue, "';");
/* 预处理动态sql语句 */
PREPARE stmt FROM @insertSQL;
/* 执行sql语句 */
EXECUTE stmt;
/* 释放prepare */
deallocate prepare stmt;
end
//

drop procedure if exists getRule_ValueReplaceDetail //
create procedure getRule_ValueReplaceDetail(in tName varchar(32), in colName varchar(16), in repID varchar(16))
comment '获取替换规则明细表'
begin

DECLARE done INT DEFAULT 0;
/* 序号 */
DECLARE repNum varchar(16);
/* 原值 */
DECLARE fValue varchar(18) DEFAULT '';
/* 替换值 */
DECLARE lValue varchar(18) DEFAULT '';
/* 更新语句 */
DECLARE colSQL varchar(500) DEFAULT '';
/* 查找替换规则明细表 */
DECLARE curRVRD CURSOR FOR SELECT Rep_Num,FirstValue,LastValue FROM Rule_ValueReplaceDetail where Rep_ID = repID;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN curRVRD;
REPEAT
	FETCH curRVRD INTO repNum,fValue,lValue;
	IF NOT done THEN
		/* 字段替换sql */
		set colSQL = CONCAT('update ',tName,' set ', colName, ' = replace(', colName, ',', "'", fValue, "',", "'", lValue, "' ); " );
		/* 预处理动态sql语句 */
		set @mySQL = colSQL;
		PREPARE stmt FROM @mySQL;
		/* 执行sql语句 */
		EXECUTE stmt;
		/* 释放prepare */
		deallocate prepare stmt;
	END IF;
UNTIL done END REPEAT;
CLOSE curRVRD;
end
//

drop procedure if exists getOriginal_ETField //
create procedure getOriginal_ETField(in tId varchar(16), in tName varchar(32), in colName varchar(16))
comment '获取清洗字段信息表'
begin

DECLARE done INT DEFAULT 0;
/* 是否主键 */
DECLARE isPK varchar(4);
/* 是否表切分字段 */
DECLARE isCutField varchar(4) DEFAULT '';
/* 切分规则 */
DECLARE cutRule varchar(40);
/* 是否进行值替换 */
DECLARE isReplace varchar(4);
/* 替换规则ID */
DECLARE repID varchar(16);
/* 查找清洗字段信息表 */
DECLARE curOETF CURSOR FOR SELECT Is_PK,Is_CutField,Cut_Rule,Is_Replace,Rep_ID FROM Original_ETField where Task_ID = tId and Field_Name = colName;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN curOETF;
REPEAT
	FETCH curOETF INTO isPK, isCutField, cutRule, isReplace, repID;
		IF NOT done THEN
			if isReplace = 'IR01' then
				call getRule_ValueReplaceDetail(tName, colName, repID);
			end if;
		END IF;
UNTIL done END REPEAT;
CLOSE curOETF;
end
//

drop procedure if exists data_clean //
create procedure data_clean(in tId varchar(16), in tName varchar(32))
comment '表和表数据清洗'
begin

DECLARE done INT DEFAULT 0;
/* 表名前缀 */
DECLARE tblPre varchar(50);
/* 是否有切分 */
DECLARE isCut varchar(4) DEFAULT 'CF02';
/* 切分规则 */
DECLARE ruleCut varchar(60);

/* 表切分语句 */
DECLARE createSql varchar(500) DEFAULT '';
/* 字段名称 */
DECLARE fieldName varchar(16);
/* 字段长度 */
DECLARE fieldLength varchar(6);
/* 字段类型 */
DECLARE fieldType varchar(12);
/* 字段含义 */
DECLARE fieldMemo varchar(60);

/* 切分规则取出 */
DECLARE myCuleCut varchar(60);
/* 切分规则key */
DECLARE cutKey varchar(10);
/* 切分规则value */
DECLARE cutValue varchar(50);

/* 查找字段定义表 */
DECLARE curOFD CURSOR FOR SELECT Field_Name,Field_Lenth,Field_Type,Field_Memo FROM Original_FieldDef where Task_ID = tId;
/* 查找元数据抽取清洗表 */
DECLARE curET CURSOR FOR SELECT Tbl_Pre,Is_Cut,Rule_Cut FROM Original_ET WHERE Task_ID = tId;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN curET;
REPEAT
	FETCH curET INTO tblPre, isCut, ruleCut;
	IF NOT done THEN
		IF isCut = 'CF01' THEN
			set myCuleCut = ruleCut;
		ELSE
			set myCuleCut = '';
		END IF;
	END IF;
UNTIL done END REPEAT;
CLOSE curET;
set done = 0;

/* 字段值替换 */
set @changeCols = '';
OPEN curOFD;
REPEAT
	FETCH curOFD INTO fieldName, fieldLength, fieldType, fieldMemo;
	IF NOT done THEN
		/* 字段名列表获取 */
		set @changeCols = CONCAT(@changeCols,fieldName,',');
	END IF;
UNTIL done END REPEAT;
CLOSE curOFD;

/* 值替换处理 */
/* 算出分隔符的总数 */
set @cols = length(@changeCols) - length(replace(@changeCols,',',''));
set @left_cols = @changeCols;
while @cols > 0 do
	/* 得到分隔符','前面的字符串 */
	set @sub_col = substr(@left_cols,1,instr(@left_cols,',')-1);
	/* 得到分隔符','后面的字符串 */
	set @left_cols = substr(@left_cols,length(@sub_col)+length(',')+1);
	set @my_col = trim(@sub_col);
	call getOriginal_ETField(tId, tName, @my_col);
	set @cols = @cols - 1;
end while;

IF myCuleCut = '' THEN
	select isCut;
ELSE
	/* 获取表切分规则key,截取第一个':'之前的所有字符 */
	set cutKey = SUBSTRING_INDEX(myCuleCut, ':', 1);
	/* 获取表切分规则value,截取倒数第一个':'之后的所有字符 */
	set cutValue = SUBSTRING_INDEX(myCuleCut, ':', -1);
	/* 算出分隔符的总数 */
	set @i = length(cutValue) - length(replace(cutValue,',',''));
	set @left_cutValue = cutValue;
	while @i > 0 do
		/* 得到分隔符','前面的字符串 */
		set @sub_str = substr(@left_cutValue,1,instr(@left_cutValue,',')-1);
		/* 得到分隔符','后面的字符串 */
		set @left_cutValue = substr(@left_cutValue,length(@sub_str)+length(',')+1);
		set @n = trim(@sub_str);
		/* 新的表名 */
		set @newTable = CONCAT(tblPre, @n);
		/* 去重复sql */
		set @repeatSQL = '';
		SET createSql = CONCAT('create table if not exists ',tblPre, @n, '(');

		set done = 0;
		OPEN curOFD;
		REPEAT
			FETCH curOFD INTO fieldName, fieldLength, fieldType, fieldMemo;
			IF NOT done THEN
				SET createSql = CONCAT(createSql,fieldName, ' ', fieldType,'(',fieldLength,')', ' ', 'COMMENT', ' ', "'", fieldMemo, "'", ',');
				/* 去重复sql拼接 */
				/*
				AND overnight_abcd.column01 = overnight_2019.column01
				AND overnight_abcd.column02 = overnight_2019.column02
				AND overnight_abcd.column03 = overnight_2019.column03
				AND overnight_abcd.column04 = overnight_2019.column04
				AND overnight_abcd.column05 = overnight_2019.column05
				*/
				set @repeatSQL = CONCAT(@repeatSQL, ' and ', tName, '.', fieldName, ' = ', @newTable, '.', fieldName);
			END IF;
		UNTIL done END REPEAT;
		set createSql = left(createSql,char_length(createSql)-1);
		set createSql = CONCAT(createSql,')ENGINE=InnoDB DEFAULT CHARSET=utf8;');
		CLOSE curOFD;
		set @sql = createSql;
		/*select @sql;*/
		/* 预处理动态sql语句 */
		PREPARE stmt FROM @sql;
		/* 执行sql语句 */
		EXECUTE stmt;
		/* 释放prepare */
		deallocate prepare stmt;
		/* 删除首个 and */
		set @repeatSQL = substr(@repeatSQL,5);
		call cutTable(tName, @newTable, cutKey, @n, @changeCols, @repeatSQL);
		set createSql = '';
		set @i = @i - 1;
	end while;

END IF;

end
//
delimiter;

/* 调用这个存储过程 */
call data_clean('OT_1001', 'overnight_abcd');

------------------------------------------------------END--------------------------------------------------

 

 


版权声明:本文为kuaikuai_945原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。