|
帮网友利用函数与存储过程解决一个分离数据的案例,供大家参考
-- Description
CREATE TABLE t1(A VARCHAR(20),B VARCHAR(20),C VARCHAR(20))ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
INSERT INTO t1(A,B,C) VALUES('1','A','1'),('2','A,B','1,2'),('3','A,B,C','1,2,3'),('4','A,B,C,D','1,2,3,4'),('5','abcde','12345');
+------+---------+---------+
| A | B | C |
+------+---------+---------+
| 1 | A | 1 |
| 2 | A,B | 1,2 |
| 3 | A,B,C | 1,2,3 |
| 4 | A,B,C,D | 1,2,3,4 |
| 5 | abcde | 12345 |
+------+---------+---------+
5 rows in set (0.00 sec)
TO ---->
+------+-------+-------+
| A | B | C |
+------+-------+-------+
| 1 | A | 1 |
| 2 | B | 2 |
| 2 | A | 1 |
| 3 | C | 3 |
| 3 | B | 2 |
| 3 | A | 1 |
| 4 | D | 4 |
| 4 | C | 3 |
| 4 | B | 2 |
| 4 | A | 1 |
| 5 | abcde | 12345 |
+------+-------+-------+
-- Code
DELIMITER $$
DROP FUNCTION IF EXISTS `fuc_split` $$
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);
SET strValue_Old=SUBSTRING_INDEX(strValue,strSplit,iPostion-1);
SET iLength_New=LENGTH(strValue_New);
IF iPostion-1<>0 THEN
SET iLength_Old=LENGTH(strValue_Old);
ELSE
SET iLength_Old=-1;
END IF;
SET iLength=iLength_New-iLength_Old;
SET strReturn=SUBSTR(strValue_new,iLength_Old+2,iLength);
RETURN strReturn;
END $$
DELIMITER ;
DELIMITER $$
DROP PROCEDURE IF EXISTS `usp_split_insert` $$
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;
DROP TEMPORARY TABLE IF EXISTS `tmp_t1`;
CREATE TEMPORARY TABLE tmp_t1(A VARCHAR(20),B VARCHAR(20),C VARCHAR(20))ENGINE=MEMORY CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
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;
SELECT * FROM tmp_t1;
END $$
DELIMITER ;
-- testing
CALL usp_split_insert(); |
|