2016-05-13 12 views
6

Otrzymałem sytuację, w której muszę przekazać ciąg odseparowany przecinkami do procedury MySQL i podzielić ten ciąg i wstawić te wartości jako wiersze do tabeli.Dzielenie ciągu znaków i przechodzenie między wartościami w procedurze MySql

Jak pokazano poniżej

na przykład jeśli zdałem „jhon, Swetha, sitha” ciąg procedury mysql to trzeba podzielić ten ciąg przecinkiem i wstawić te wartości jako 3 rekordy do tabeli.

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 

Ale to nie zadziałało, proszę.

Odpowiedz

16

Musisz być bardziej ostrożny przy manipulowaniu strunami. Nie można w tym celu użyć REPLACE(), ponieważ zastąpi to wiele wystąpień, powodując uszkodzenie danych, jeśli jeden element na liście rozdzielanej przecinkami jest podciąńcem innego elementu. Model INSERT() string function jest lepszy do tego, nie mylić z instrukcją INSERT używaną do wstawiania do tabeli.

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 ; 

Następny, stół do badań:

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

Nowa tabela jest pusta.

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

Zadzwoń do procedury.

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

Uwaga: "1 wiersz dotknięty" nie oznacza tego, czego można się spodziewać. Odnosi się do ostatniej wstawki, którą zrobiliśmy. Ponieważ wstawiamy jeden wiersz naraz, jeśli procedura wstawia co najmniej jeden wiersz, zawsze otrzymasz liczbę wierszy równą 1; jeśli procedura nic nie wstawi, dostaniesz 0 wierszy, których dotyczy.

Czy to działa?

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

Bardzo przydatna odpowiedź. –

Powiązane problemy