Как разделить текст через запятую в хранимой процедуре MySQL - PullRequest
16 голосов
/ 02 февраля 2010

Как разделить текст через запятую (список идентификаторов) в хранимой процедуре MySQL, чтобы использовать результат в операторе SQL «IN».

SELECT * FROM table WHERE table.id IN (splitStringFunction(commaSeparatedData, ','));

Ответы [ 8 ]

41 голосов
/ 26 марта 2014

Для MySQL это просто ад:

SELECT * FROM table WHERE FIND_IN_SET(table.id, commaSeparatedData);

Ссылка: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set

5 голосов
/ 12 апреля 2013

Вы можете использовать подготовленный оператор внутри хранимой процедуры для достижения этой цели. Вы можете создать весь запрос на выборку в виде строки внутри переменной, а затем объединить в строке с разделителями-запятыми ее предложение IN. Затем вы можете сделать подготовленный оператор из строковой переменной запроса и выполнить его.

DELIMITER ;;
create procedure testProc(in listString varchar(255))

BEGIN

set @query = concat('select * from testTable where id in (',listString,');');
prepare sql_query from @query;
execute sql_query;

END
;;

DELIMITER ;

call testProc("1,2,3");
4 голосов
/ 05 февраля 2010

Вы можете попробовать этот пример MySql. Прежде чем использовать его, поместите в него некоторые проверки безопасности типов (т. Е. Проверьте, что id является целым числом или соответствует регулярному выражению перед вставкой).

 # BEGIN split statements ids
 DECLARE current_pos INT DEFAULT 1;
 DECLARE delim CHAR DEFAULT ',';
 DECLARE current CHAR DEFAULT '';
 DECLARE current_id VARCHAR(100) DEFAULT '';;
 CREATE TEMPORARY TABLE ids (`id` VARCHAR(100));
 split_ids: LOOP
  SET current = MID(statement_ids, current_pos, 1);
  IF (current_pos = LENGTH(statement_ids)) THEN
   IF current != delim THEN SET current_id = CONCAT(current_id,current); END IF;
   INSERT INTO ids(id) VALUES (current_id);
   LEAVE split_ids;
  END IF;
  IF current = delim THEN
   INSERT INTO ids(id) VALUES (current_id);
   SET current_id = '';
  ELSE
   SET current_id = CONCAT(current_id,current);
  END IF;
  SET current_pos = current_pos+1;
 END LOOP split_ids;
 # END split statement ids

 # to check ids are correct
 SELECT * FROM ids;

 # to use the ids:
 SELECT * FROM statements WHERE id IN (SELECT id FROM ids);
4 голосов
/ 02 февраля 2010

Вы можете сделать это двумя способами:

  1. Библиотека SQL
  2. Собственно с REGEXP
2 голосов
/ 08 апреля 2011

ОК, немного «проще», но менее навязчиво для таких людей, как я:

скажем, у вас есть одна таблица 'comb_city_state', которая выглядит следующим образом:

'Chicago, Illinois'

скопируйте ее в 2 другихтаблицы:

CREATE TABLE city LIKE combined_city_state;
INSERT city SELECT * FROM combined_city_state;

CREATE TABLE state LIKE combined_city_state;
INSERT state SELECT * FROM combined_city_state;

Теперь у вас есть 3 таблицы с такими же данными, как и в сочетании с_state.

Установите эту функцию:

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');

Затем примените это к каждой таблицечтобы удалить дополнительный индекс данных:

UPDATE firms 
SET city = (SELECT SPLIT_STR((city), ',', 1));


UPDATE firms 
SET state = (SELECT SPLIT_STR((state), ',', 2));

Это оставит вас с одним столбцом только городов, одним из только штатов.Теперь вы можете удалить исходный столбец «комбинированный_город», если он вам больше не нужен.

1 голос
/ 30 декабря 2013

Я удивлен, что эта строка не упоминается здесь должным образом:

SELECT * FROM table
WHERE id in (SELECT convert(int,Value) FROM dbo.Split(@list_string,',')

Все, что вам нужно, это функция Split SQL , подобная приведенной ниже, которая пригодится и в других случаях:

CREATE FUNCTION dbo.Split
(
    @List nvarchar(2000),
    @SplitOn nvarchar(5)
)  
RETURNS @RtnValue table 
(

    Id int identity(1,1),
    Value nvarchar(100)
) 
AS  
BEGIN
While (Charindex(@SplitOn,@List)>0)
Begin
    Insert Into @RtnValue (value)
    Select 
        Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1)))
        Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List))
End

Insert Into @RtnValue (Value)
Select Value = ltrim(rtrim(@List))

Return
END
0 голосов
/ 07 июня 2019

Немного странно, но:

SET @i = 1;
set @str = 'a,b,c,d,e,f,g,h';

select temp.length into @length from 
(select
        ROUND(   
            (
                LENGTH(dt.data)
                - LENGTH( REPLACE (dt.data, ",", "") ) 
            ) / LENGTH(",")        
        )+1 AS length   
     from (select @str as data) dt
 ) temp;

SET @query = CONCAT('select substring_index(
    substring_index(@str, '','', seq), 
    '','', 
    -1
  ) as letter from seq_', @i, '_to_',@length);

PREPARE q FROM @query;
EXECUTE q;
0 голосов
/ 27 августа 2013

Я проанализировал данные с дефисами в нем. В приведенном ниже примере для демонстрации используется фиксированная текстовая строка, просто измените ссылки на соответствующие имена столбцов в таблице. Я играл целую вечность, чтобы убедиться, что он работает с кодами с различным количеством компонентов, и в конце концов решил добавить предложение where. Большинство данных, которые вы пытаетесь проанализировать, имеют фиксированное количество столбцов.

select
SUBSTRING_INDEX(TS,"-",1) as "1",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",2)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",2)))-1)) as "2",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",3)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",3)))-1)) as "3",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",4)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",4)))-1)) as "4",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",5)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",5)))-1)) as "5",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",6)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",6)))-1)) as "6",reverse(left(reverse(SUBSTRING_INDEX(TS,"-",7)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",7)))-1)) as "7",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",8)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",8)))-1)) as "8",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",9)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",9)))-1)) as "9",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",10)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",10)))-1)) as "10"
from (select "aaa-bbb-ccc-ddd-eee-fff-ggg-hhh-iii-jjj" as TS) as S
where (LENGTH(TS)-LENGTH(REPLACE(TS,'-',''))) =9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...