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

标签 mysql csv stored-procedures

存储过程(在 csvString varchar(1000) 中)

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

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

Expected output

如果 csv 字符串为 1,2,3,4,5,6,7,8 则

Expected output

提前致谢

最佳答案

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

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 .

关于mysql - 使用 MySQL 存储过程将 CSV 字符串转换为表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44322172/

相关文章:

vb.net - DataGridView 转 CSV 文件

c# - SQLMetal 无法从 SQL Server 2005 数据库创建 DBML

mysql触发器语法错误

php - Mysql查询select需要很多时间

javascript - 将 CSV 从实时 URL 解析为 HTML 表

mysql - 如何在存储过程中创建变量游标?

php - 使用存储过程列出记录

mysql - 显示所有日期和日期,无论是否存在记录

java - 是否有 MySQL 的 Spring Batch 3 升级脚本?

java - 正则表达式处理逗号、双引号、引号