2016-05-13 2 views
6

Ich habe eine Situation, wo ich eine Komma getrennte Zeichenfolge an MySQL-Prozedur übergeben müssen und teilen Sie diese Zeichenfolge und fügen Sie diese Werte als Zeilen in eine Tabelle.Teilen Sie eine Zeichenfolge und Schleife durch Werte in MySql Prozedur

Als zeigen unter

Zum Beispiel, wenn ich bestanden ‚jhon, swetha, Sitha‘ string zu mysql Prozedur dann müssen sie diese Zeichenfolge durch Komma aufgespalten und diese Werte als 3 Datensätze in eine Tabelle einfügen.

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 

Aber das hat keine Lösung bitte funktioniert.

Antwort

16

Sie müssen ein bisschen vorsichtiger mit Ihrer String-Manipulation sein. Sie können dafür REPLACE() nicht verwenden, da dadurch mehrere Vorkommen ersetzt werden und Ihre Daten beschädigt werden, wenn ein Element in der durch Kommas getrennten Liste ein Teilstring eines anderen Elements ist. Die INSERT() string function ist dafür besser, nicht mit der INSERT Anweisung zu verwechseln, die für das Einfügen in eine Tabelle verwendet wird.

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 ; 

Als nächstes wird eine Tabelle für die Prüfung:

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

Die neue Tabelle ist leer.

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

Rufen Sie das Verfahren auf.

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

Beachten Sie die "1 Zeile betroffen" bedeutet nicht, was Sie erwarten würden. Es bezieht sich auf den letzten Einsatz, den wir gemacht haben. Da wir jeweils eine Zeile einfügen, wenn die Prozedur mindestens eine Zeile einfügt, erhalten Sie immer eine Zeilenanzahl von 1; Wenn die Prozedur nichts einfügt, erhalten Sie 0 Zeilen betroffen.

Hat es funktioniert?

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

Sehr nützliche Antwort. –

Verwandte Themen