使用MySQL存储过程将CSV字符串转换为表

时间:2017-06-02 06:25:06

标签: mysql csv stored-procedures

StoredProcedure(在csvString varchar(1000)中)

csvString有1,2,3,4,5,6

我希望将此csv字符串放入如下表

Expected output

如果csv string是1,2,3,4,5,6,7,8那么

Expected output

提前致谢

1 个答案:

答案 0 :(得分:0)

根据需要进行验证和调整:

mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.18    |
+-----------+
1 row in set (0.00 sec)

mysql> DROP PROCEDURE IF EXISTS `insert_split`;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP FUNCTION IF EXISTS `split_str`;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE IF EXISTS `tbl`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE IF NOT EXISTS `tbl` (
    ->   `col1` VARCHAR(255),
    ->   `col2` VARCHAR(255)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> -- MySQL Split String Function by Federico Cargnelutti
mysql> -- http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
mysql> CREATE FUNCTION `split_str` (
    -> `str` TEXT,
    -> `delim` CHAR(1),
    -> `item` INT UNSIGNED
    -> ) RETURNS VARCHAR(255)
    -> BEGIN
    ->   DECLARE `_current_str` TEXT DEFAULT SUBSTRING_INDEX(`str`, `delim`, `item`);
    ->   DECLARE `_prev_str` TEXT DEFAULT SUBSTRING_INDEX(`str`, `delim`, `item`-1);
    ->   IF `_current_str` = `_prev_str` THEN
    ->     RETURN NULL;
    ->   ELSE
    ->     RETURN REPLACE(
    ->       SUBSTRING(
    ->         `_current_str`,
    ->         CHAR_LENGTH(`_prev_str`) + 1
    ->       ),
    ->     `delim`, '');
    ->   END IF;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //

mysql> CREATE PROCEDURE `insert_split`(`str` TEXT)
    -> BEGIN
    ->   DECLARE `_delim` CHAR(1) DEFAULT ',';
    ->   DECLARE `_iteration` INT UNSIGNED DEFAULT 0;
    ->   DECLARE `_current_value` VARCHAR(255);
    ->   DECLARE `_odd_value` VARCHAR(255) DEFAULT '';
    ->   `repeat`: LOOP
    ->     SET `_iteration` := `_iteration` + 1;
    ->     SET `_current_value` := `split_str`(`str`, `_delim`, `_iteration`);
    ->     IF `_current_value` IS NULL THEN
    ->       LEAVE `repeat`;
    ->     END IF;
    ->     IF (`_iteration` MOD 2) = 0 THEN
    ->       INSERT INTO `tbl` (`col1`, `col2`)
    ->       VALUES (NULLIF(`_odd_value`, ''), NULLIF(`_current_value`, ''));
    ->     ELSE
    ->       SET `_odd_value` := `_current_value`;
    ->     END IF;
    ->   END LOOP `repeat`;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

mysql> CALL `insert_split`('1,2,3,4,5,6');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `col1`, `col2`
    -> FROM `tbl`;
+------+------+
| col1 | col2 |
+------+------+
| 1    | 2    |
| 3    | 4    |
| 5    | 6    |
+------+------+
3 rows in set (0.00 sec)

mysql> TRUNCATE TABLE `tbl`;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL `insert_split`('1,2,3,4,5,6,7,8');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `col1`, `col2`
    -> FROM `tbl`;
+------+------+
| col1 | col2 |
+------+------+
| 1    | 2    |
| 3    | 4    |
| 5    | 6    |
| 7    | 8    |
+------+------+
4 rows in set (0.00 sec)

请参阅db-fiddle

<强>更新

如果您使用奇数和偶数值,则可以使用以下内容:

mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.18    |
+-----------+
1 row in set (0.00 sec)

mysql> DROP PROCEDURE IF EXISTS `insert_split`;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP FUNCTION IF EXISTS `split_str`;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE IF EXISTS `tbl`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE IF NOT EXISTS `tbl` (
    ->   `col1` VARCHAR(255),
    ->   `col2` VARCHAR(255)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //

mysql> -- MySQL Split String Function by Federico Cargnelutti
mysql> -- http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
mysql> CREATE FUNCTION `split_str` (
    -> `str` TEXT,
    -> `delim` CHAR(1),
    -> `item` INT UNSIGNED,
    -> `max_len_str` SMALLINT UNSIGNED
    -> ) RETURNS VARCHAR(255)
    -> BEGIN
    ->   DECLARE `_current_str` TEXT DEFAULT SUBSTRING_INDEX(`str`, `delim`, `item`);
    ->   DECLARE `_prev_str` TEXT DEFAULT SUBSTRING_INDEX(`str`, `delim`, `item`-1);
    ->   IF `_current_str` = `_prev_str` AND CHAR_LENGTH(`_prev_str`) = `max_len_str`  THEN
    ->     RETURN NULL;
    ->   ELSE
    ->     RETURN REPLACE(
    ->       SUBSTRING(
    ->         `_current_str`,
    ->         CHAR_LENGTH(`_prev_str`) + 1
    ->       ),
    ->     `delim`, '');
    ->   END IF;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE PROCEDURE `insert_split`(`str` TEXT)
    -> BEGIN
    ->   DECLARE `_max_length_str` SMALLINT UNSIGNED DEFAULT CHAR_LENGTH(`str`);
    ->   DECLARE `_delim` CHAR(1) DEFAULT ',';
    ->   DECLARE `_iteration` INT UNSIGNED DEFAULT 0;
    ->   DECLARE `_odd_value`, `_even_value` VARCHAR(255);
    ->   `repeat`: LOOP
    ->     SET `_odd_value` := `split_str`(`str`, `_delim`, `_iteration` + 1, `_max_length_str`);
    ->     SET `_even_value` := `split_str`(`str`, `_delim`, `_iteration` + 2, `_max_length_str`);
    ->     IF `_odd_value` IS NULL AND `_even_value` IS NULL THEN
    ->       LEAVE `repeat`;
    ->     END IF;
    ->     INSERT INTO `tbl` (`col1`, `col2`)
    ->     VALUES (NULLIF(`_odd_value`, ''), NULLIF(`_even_value`, ''));
    ->     SET `_iteration` := `_iteration` + 2;
    ->   END LOOP `repeat`;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

mysql> TRUNCATE TABLE `tbl`;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL `insert_split`('1,2,3,4,5,6');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `col1`, `col2`
    -> FROM `tbl`;
+------+------+
| col1 | col2 |
+------+------+
| 1    | 2    |
| 3    | 4    |
| 5    | 6    |
+------+------+
3 rows in set (0.00 sec)

mysql> TRUNCATE TABLE `tbl`;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL `insert_split`('1,2,3,4,5,6,7,8');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `col1`, `col2`
    -> FROM `tbl`;
+------+------+
| col1 | col2 |
+------+------+
| 1    | 2    |
| 3    | 4    |
| 5    | 6    |
| 7    | 8    |
+------+------+
4 rows in set (0.00 sec)

mysql> TRUNCATE TABLE `tbl`;
Query OK, 0 rows affected (0.01 sec)

mysql> CALL `insert_split`(',,,');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `col1`, `col2`
    -> FROM `tbl`;
+------+------+
| col1 | col2 |
+------+------+
| NULL | NULL |
| NULL | NULL |
+------+------+
2 rows in set (0.00 sec)

mysql> TRUNCATE TABLE `tbl`;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL `insert_split`(',1,,,3');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT `col1`, `col2`
    -> FROM `tbl`;
+------+------+
| col1 | col2 |
+------+------+
| NULL | 1    |
| NULL | NULL |
| 3    | NULL |
+------+------+
3 rows in set (0.00 sec)

请参阅db-fiddle