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--------------------------------------------------

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章