Как разбить текст, разделенный запятыми (список идентификаторов) в хранимой процедуре MySQL, чтобы использовать результат в инструкции SQL "IN".
SELECT * FROM table WHERE table.id IN (splitStringFunction(commaSeparatedData, ','));
Как разбить текст, разделенный запятыми (список идентификаторов) в хранимой процедуре MySQL, чтобы использовать результат в инструкции SQL "IN".
SELECT * FROM table WHERE table.id IN (splitStringFunction(commaSeparatedData, ','));
Вы можете сделать это двумя способами:
Это просто для 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
Для достижения этой цели вы можете использовать подготовленный оператор внутри хранимой процедуры. Вы можете создать весь запрос select как строку внутри переменной и затем объединить в строку с разделителями-запятыми в свой раздел 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");
Вы можете попробовать этот пример MySql. Прежде чем использовать его, поместите туда некоторые проверки безопасности (т.е. Идентификатор проверки равен целому числу или соответствует регулярному выражению перед вставкой).
# 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);
ОК, немного "легче", но менее вызывающий способ для таких людей, как я:
скажем, что у вас есть одна таблица 'combination_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 таблицы с теми же данными, что и "combined_city_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));
Это оставляет вам один столбец только городов, одного из состояний. Теперь вы можете удалить исходный столбец "mixed_city_state", если вам больше не нужно.
Я удивлен, что этот однострочный лайнер здесь не упомянут:
SELECT * FROM table
WHERE id in (SELECT convert(int,Value) FROM dbo.Split(@list_string,',')
Все, что вам нужно, это Split SQL function, как тот, который ниже, который также пригодится и другими способами:
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
Я проанализировал данные с дефисами в нем. В приведенном ниже примере используется фиксированная текстовая строка для демонстрации, просто измените ссылки на соответствующие имена столбцов в таблице. Я играл целую вечность, чтобы обеспечить его работу с кодами с различным количеством компонентов и в конце концов решил добавить предложение 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
Немного странно, но:
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;