MySql: хранимая процедура для разделения, возврат таблицы

0

Я нашел много примеров split-процедур для MySql, возвращающих x-часть строки. Но мне нужна сплит-процедура, чтобы вернуть ВСЕ части расщепленной строки, так что вроде как:

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)

Каков правильный способ сделать это?

  • 0
    Вы смешиваете процедуры и функции - процедуры не имеют RETURNS, а mysql не поддерживает функции с табличными значениями.
  • 0
    Это никогда не будет работать так, как вы бы хотели, чтобы оно работало ... хранимая процедура не может быть вызвана с помощью SELECT, вам нужно использовать CALL ... можно сделать функцию, которая работает с select, но не может возвращать несколько записей.
Теги:

1 ответ

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню