2016-05-13 3 views
6

コンマ区切りの文字列をMySQLプロシージャに渡してその文字列を分割し、それらの値を行としてテーブルに挿入する必要があります。私はMySQLの手順に「JHON、swetha、sitha」文字列を渡された場合、それはコンマでその文字列を分割し、テーブルに3つのレコードとしてこれらの値を挿入する必要があり、例えば文字列を分割してMySqlの値をループします。

以下ショーとして

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

文字列の操作に少し注意する必要があります。カンマで区切られたリストの1つの要素が別の要素の部分文字列である場合、データが破損し、複数の箇所が置き換えられるため、REPLACE()を使用することはできません。 INSERT() string functionはこれには適していますが、テーブルに挿入するために使用される文と混同しないでください。

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行を挿入するので、を少なくとも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

非常に便利な回答です。 –

関連する問題