2016-05-13 106 views
6

我遇到了一種情況,必須將逗號分隔的字符串傳遞給MySQL過程並拆分該字符串,並將這些值作爲行插入到表中。拆分字符串並循環遍歷MySql中的值過程

如下面

節目例如,如果我通過「約翰,swetha,sitha」字符串到MySQL程序然後它必須通過分離逗號該字符串並插入這些值作爲3條記錄到表中。

CREATE PROCEDURE new_routine (IN str varchar(30)) 
    BEGIN 
     DECLARE tmp varchar(10); 
     DECLARE inc INT DEFAULT 0; 
     WHILE INSTR(str, ',') DO 
     SET tmp = SUBSTRING(SUBSTRING_INDEX(str,',',inc),LENGTH(SUBSTRING_INDEX(str,',',inc-1))+1),',',''); 
     SET str = REPLACE(str, tmp, ''); 
     //insert tmp into a table. 
     END WHILE; 
    END 

但是,這不起作用的任何解決方案,請。

回答

16

你需要對你的字符串操作更加小心。您不能使用REPLACE(),因爲這會替換多個匹配項,如果逗號分隔列表中的某個元素是另一個元素的子字符串,則會損壞您的數據。 INSERT() string function對此更好,不要與用於插入表的INSERT語句混淆。

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `insert_csv` $$ 
CREATE PROCEDURE `insert_csv`(_list MEDIUMTEXT) 
BEGIN 

DECLARE _next TEXT DEFAULT NULL; 
DECLARE _nextlen INT DEFAULT NULL; 
DECLARE _value TEXT DEFAULT NULL; 

iterator: 
LOOP 
    -- exit the loop if the list seems empty or was null; 
    -- this extra caution is necessary to avoid an endless loop in the proc. 
    IF LENGTH(TRIM(_list)) = 0 OR _list IS NULL THEN 
    LEAVE iterator; 
    END IF; 

    -- capture the next value from the list 
    SET _next = SUBSTRING_INDEX(_list,',',1); 

    -- save the length of the captured value; we will need to remove this 
    -- many characters + 1 from the beginning of the string 
    -- before the next iteration 
    SET _nextlen = LENGTH(_next); 

    -- trim the value of leading and trailing spaces, in case of sloppy CSV strings 
    SET _value = TRIM(_next); 

    -- insert the extracted value into the target table 
    INSERT INTO t1 (c1) VALUES (_next); 

    -- rewrite the original string using the `INSERT()` string function, 
    -- args are original string, start position, how many characters to remove, 
    -- and what to "insert" in their place (in this case, we "insert" 
    -- an empty string, which removes _nextlen + 1 characters) 
    SET _list = INSERT(_list,1,_nextlen + 1,''); 
END LOOP; 

END $$ 

DELIMITER ; 

接下來,測試表:

CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `c1` varchar(64) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

新表是空的。

mysql> SELECT * FROM t1; 
Empty set (0.00 sec) 

調用程序。

mysql> CALL insert_csv('foo,bar,buzz,fizz'); 
Query OK, 1 row affected (0.00 sec) 

請注意,「1行受影響」並不意味着你期望的。它指的是我們所做的最後一個插入。由於我們一次插入一行,如果程序至少插入一行,您將始終得到1的行數;如果該過程沒有插入任何內容,則會得到0行受影響。

它工作嗎?

mysql> SELECT * FROM t1; 
+----+------+ 
| id | c1 | 
+----+------+ 
| 1 | foo | 
| 2 | bar | 
| 3 | buzz | 
| 4 | fizz | 
+----+------+ 
4 rows in set (0.00 sec) 
+0

非常有用的答案。 –