Você precisará ser um pouco mais cuidadoso com a manipulação de strings. Você não pode usar
REPLACE()
para isso, porque isso substituirá várias ocorrências, corrompendo seus dados se um elemento na lista separada por vírgulas for uma substring de outro elemento. O INSERT()
função string
é melhor para isso, não deve ser confundido com o INSERT
instrução usada para inserir em uma tabela. 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 CHAR_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 = CHAR_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 (_value);
-- 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 ;
A seguir, uma tabela para teste:
CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`c1` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
A nova tabela está vazia.
mysql> SELECT * FROM t1;
Empty set (0.00 sec)
Chame o procedimento.
mysql> CALL insert_csv('foo,bar,buzz,fizz');
Query OK, 1 row affected (0.00 sec)
Observe que "1 linha afetada" não significa o que você esperaria. Refere-se à última inserção que fizemos. Como inserimos uma linha por vez, se o procedimento inserir pelo menos uma linha, você sempre obterá uma contagem de linhas de 1; se o procedimento não inserir nada, você obterá 0 linhas afetadas.
Funcionou?
mysql> SELECT * FROM t1;
+----+------+
| id | c1 |
+----+------+
| 1 | foo |
| 2 | bar |
| 3 | buzz |
| 4 | fizz |
+----+------+
4 rows in set (0.00 sec)