MySql:分割,返回表的存储过程

时间:2018-04-10 13:43:11

标签: mysql

我发现很多MySql拆分过程的例子都返回了字符串的xth部分。但我需要一个拆分程序来返回拆分字符串的所有部分,所以像:

SELECT split(",", "1,2,3,4,5,6");

应该返回;

+-------+
| split |
+-------+
|     1 |
|     2 |
|     3 |
|     4 |
|     5 |
|     6 |
+-------+

我试过了:

DELIMITER $$

CREATE PROCEDURE `split`(delimeter VARCHAR(1),txt VARCHAR(65535))
RETURNS split TABLE (
  part varchar(1024) NOT NULL)
DETERMINISTIC
BEGIN

DECLARE pos, posOld;

set pos := locate(delimeter,txt);
set posOld = 1;

WHILE pos > 0 DO
 set part := subst(text, posOld, pos-1);
 set posOld := pos+1;
 insert into split (`part`) values (part);

 set pos := locate(delimeter, txt, posOld);
END WHILE;

END$$

但得到错误:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'split TABLE (part varchar(1024) NOT NULL)

这是正确的方法吗?

1 个答案:

答案 0 :(得分:2)

您只能使用纯SQL执行此操作。
这个技巧是将MySQL数字生成器与嵌套的SUBSTRING_INDEX函数结合使用。

<强>查询

此查询将生成1到100之间的数字 因此,最终查询最多可支持100个分隔值。

SELECT 
 (@number  := @number + 1) AS number
FROM (
  SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) AS record_1
CROSS JOIN (
  SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) AS record_2
CROSS JOIN ( SELECT @number := 0 ) AS init_user_param

参见演示http://sqlfiddle.com/#!9/c314ca/5

现在我们将使用

从逗号分隔的字符串中提取值

<强>查询

将[position]替换为0 - 5中要从逗号分隔字符串中提取的值。

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('1,2,3,4,5', ',', [position]), ',', -1) AS split;

参见演示http://sqlfiddle.com/#!9/c314ca/16

现在我们知道了将两个查询结合到工作解决方案的基础知识。

<强>查询

SELECT
  DISTINCT 
    SUBSTRING_INDEX(SUBSTRING_INDEX(@CSV, ',', generator.number), ',', -1) AS split
FROM (

  SELECT 
   (@number  := @number + 1) AS number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) AS record_1
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) AS record_2
  CROSS JOIN ( SELECT @number := 0 ) AS init_user_param
) 
 AS generator
CROSS JOIN (
  SELECT @CSV := '1,2,3,4,5'
) AS init_user_param

参见演示http://sqlfiddle.com/#!9/c314ca/20