2016-05-13 51 views
6

'daki değerler arasında geçiş yapma Bir virgülle ayrılmış dizeyi MySQL yordamına iletmem ve bu dizeyi bölmek ve bu değerleri satır olarak bir tabloya eklemek zorunda olduğum bir durum var. ÖrneğinBir dize ve MySql Procedure

aşağıda gösterdiği gibi

Ben geçtiyseniz 'jhon, swetha, sitha' MySQL prosedürüne dize sonra virgül ile bu dize bölmek ve bir tabloya 3 kayıtları gibi bu değerleri eklemek gerekir.

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 

bu türlü çözüme çalıştı gelmez Ama lütfen.

cevap

16

Dize işleminizde biraz daha dikkatli olmanız gerekir. Bunun için REPLACE() kullanamazsınız, çünkü virgülle ayrılmış listedeki bir öğe başka bir öğenin alt dizesiyse, verilerinizi bozacak ve birden çok yinelemenin yerini alacaktır. INSERT() string function bunun için daha iyidir, tabloya eklemek için kullanılan INSERT deyimiyle karıştırılmamalıdır.

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 ; 

Daha sonra, test için bir tablo:

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

yeni tablo boştur. Prosedürü çağırın.

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

Not "etkilenen 1 satır" ne beklediğiniz anlamına gelmez. Yaptığımız son eki ifade eder. Her seferinde bir satır eklediğimizden, yordam en az tek satır eklerse, her zaman 1 satır sayısı alırsınız; Prosedür hiçbir şey eklemezse, 0 satırdan etkilenir.

Çalıştı mı?

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

Çok faydalı yanıt. –