带分割符号列值记录拆分成多行的实现方式

来源:互联网 发布:数据库实时同步 编辑:程序博客网 时间:2024/06/07 05:51

先给各位读者描述下,论坛中技友所提的问题及想要实现的效果:
1.某表中存在的数据记录格式

表T
A B C
1 a,b,c 2,3,4
2 m,n ,c 4,5,8
3 l,k,g,h 6,8,9,11

2.对带有分隔符号的列:B、C,进行拆分得到如下的效果
表T1
A B C
1 a 2
1 b 3
1 c 4
2 m 4
2 n 5
2 c 8
3 l 6
3 k 8
3 g 9
3 h 11

需求分析后,可提取的信息:
1>.需要拆分的列为:B、C,A列的值不变,属于1拆多的;
2>.B,C列值对应拆分成多条记录;
3>.列B,C的值域分割符号为英文输入法下的逗号(,);
4>.列B,C中的分隔符号个数不固定;
5>.列B,C值的结尾无分割符号;

为实现其记录转换的效果,需要完成三件事,如下:

1>.编写一个通用性质的记录拆分函数
DELIMITER $$
CREATE FUNCTION fuc_split(strValue VARCHAR(20),strSplit CHAR(1),iPostion TINYINT)
RETURNS VARCHAR(10) DETERMINISTIC
BEGIN
DECLARE strValue_New VARCHAR(20) DEFAULT ”;
DECLARE strValue_Old VARCHAR(20) DEFAULT ”;
DECLARE strReturn VARCHAR(10) DEFAULT ”;

DECLARE iLength_Old TINYINT DEFAULT 0;
DECLARE iLength_New TINYINT DEFAULT 0;
DECLARE iLength TINYINT DEFAULT 0;

SET strValue_New=SUBSTRING_INDEX(strValue,strSplit,iPostion);
IF iPostion-1<>0 THEN
SET strValue_Old=SUBSTRING_INDEX(strValue,strSplit,iPostion-1);
ELSE
SET strValue_Old=”;
END IF;

SET iLength_New=LENGTH(strValue_New);
SET iLength_Old=LENGTH(strValue_Old);
SET iLength=iLength_New-iLength_Old;

SET strReturn=SUBSTR(strValue_new,iLength_Old+1,iLength);

RETURN strReturn;
END $$
DELIMITER ;

2>.创建一张用于存储拆分之后的记录存放表

CREATE TABLE tmp_t1(A VARCHAR(20),B VARCHAR(20),C VARCHAR(20))ENGINE=InnoDB CHARACTER SET ‘utf8′ COLLATE ‘utf8_general_ci’;

3>.编写一个存储过程用于转换当前表中的每一条

DELIMITER $$
CREATE PROCEDURE usp_split_insert()
BEGIN
DECLARE strValue_A VARCHAR(20) DEFAULT ”;
DECLARE strValue_B VARCHAR(20) DEFAULT ”;
DECLARE strValue_C VARCHAR(20) DEFAULT ”;

DECLARE strValue_B_tmp VARCHAR(20) DEFAULT ”;
DECLARE strValue_C_tmp VARCHAR(20) DEFAULT ”;

DECLARE iLength_Old TINYINT DEFAULT 0;
DECLARE iLength_New TINYINT DEFAULT 0;
DECLARE iLength TINYINT DEFAULT 0;
DECLARE iFlag TINYINT DEFAULT 0;

DECLARE  cur_t1  CURSOR  FOR SELECT A,B,C FROM T1;
DECLARE CONTINUE HANDLER FOR SQLSTATE ’02000′ SET iFlag=1;

OPEN cur_t1;
FETCH cur_t1 INTO strValue_A,strValue_B,strValue_c;

WHILE iFlag<>1
DO
SET iLength_Old=LENGTH(strValue_B);
SET iLength_New=LENGTH(TRIM(REPLACE(strValue_B,’,',”)));

SET iLength=iLength_Old-iLength_New+1;
WHILE iLength<>0
DO

SET strValue_B_tmp=fuc_split(strValue_B,’,',iLength);
SET strValue_C_tmp=fuc_split(strValue_C,’,',iLength);
INSERT INTO tmp_t1(A,B,C) VALUES(strValue_A,strValue_B_tmp,strValue_C_tmp);

SET iLength=iLength-1;
END WHILE;

SET iLength=0;
SET iLength_Old=0;
SET iLength_New=0;

FETCH cur_t1 INTO strValue_A,strValue_B,strValue_c;
END WHILE;

CLOSE cur_t1 ;

SELECT * FROM tmp_t1 LIMIT 10;

END $$
DELIMITER ;

只要把上述三步的代码在对应的数据库中执行完毕,然后再执行存储过程:

CALL usp_split_insert();

其效果即完成。

原创粉丝点击