Передача массива в MySQL
Мне нужно передать массив строк в качестве параметра в хранимую процедуру MySQL. Массив может быть длинным, а количество элементов не фиксировано. Затем я хочу поместить строковые значения в таблицу в памяти с одним столбцом, чтобы я мог работать с данными. Я не знаю, можно ли это сделать в MySQL. Возможно, нужны грязные обходные пути.
Например, у меня есть строковые значения:
Banana, Apple, Orange
Теперь я хочу получить данные о этих фруктах из таблицы MySQL Fruits
. Псевдокод:
create function GetFruits(Array fruitArray)
declare @temp table as
fruitName varchar(100)
end
@temp = convert fruitArray to table
select * from Fruits where Name in (select fruitName from @temp)
end
Microsoft SQL Server позволяет использовать тип данных TEXT
и передавать массив как строку XML, быстро создавая таблицу в памяти. Тем не менее, я не думаю, что этот метод возможен в MySQL.
Любая помощь в том, как это сделать, будет оценена по достоинству!
Ответы
Ответ 1
Вы можете передать строку со своим списком и использовать подготовленные инструкции для запуска запроса, например. -
DELIMITER $$
CREATE PROCEDURE GetFruits(IN fruitArray VARCHAR(255))
BEGIN
SET @sql = CONCAT('SELECT * FROM Fruits WHERE Name IN (', fruitArray, ')');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;
Как использовать:
SET @fruitArray = '\'apple\',\'banana\'';
CALL GetFruits(@fruitArray);
Ответ 2
Просто используйте FIND_IN_SET:
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
-> 2
чтобы вы могли:
select * from Fruits where FIND_IN_SET(fruit, fruitArray) > 0
Ответ 3
Это помогает мне выполнить условие IN
Надеюсь, это поможет вам.
CREATE PROCEDURE `test`(IN Array_String VARCHAR(100))
BEGIN
SELECT * FROM Table_Name
WHERE FIND_IN_SET(field_name_to_search, Array_String);
END//;
Вызов:
call test('3,2,1');
Ответ 4
Используйте соединение с временной таблицей. Вам не нужно передавать временные таблицы в функции, они глобальны.
create temporary table ids( id int ) ;
insert into ids values (1),(2),(3) ;
delimiter //
drop procedure if exists tsel //
create procedure tsel() -- uses temporary table named ids. no params
READS SQL DATA
BEGIN
-- use the temporary table `ids` in the SELECT statement or
-- whatever query you have
select * from Users INNER JOIN ids on userId=ids.id ;
END //
DELIMITER ;
CALL tsel() ; -- call the procedure
Ответ 5
Если вы не хотите использовать временные таблицы, здесь есть разделенная строка, такая как функция, которую вы можете использовать
SET @Array = 'one,two,three,four';
SET @ArrayIndex = 2;
SELECT CASE
WHEN @Array REGEXP CONCAT('((,).*){',@ArrayIndex,'}')
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@Array,',',@ArrayIndex+1),',',-1)
ELSE NULL
END AS Result;
-
SUBSTRING_INDEX(string, delim, n)
возвращает первый n
-
SUBSTRING_INDEX(string, delim, -1)
возвращает только последний
-
REGEXP '((delim).*){n}'
проверяет, есть ли n разделителей (т.е. вы находитесь в границах)
Ответ 6
У меня появилось неловкое, но функциональное решение для моей проблемы. Он работает для одномерного массива (больше измерений будет сложным) и ввода, который вписывается в varchar
:
declare pos int; -- Keeping track of the next item position
declare item varchar(100); -- A single item of the input
declare breaker int; -- Safeguard for while loop
-- The string must end with the delimiter
if right(inputString, 1) <> '|' then
set inputString = concat(inputString, '|');
end if;
DROP TABLE IF EXISTS MyTemporaryTable;
CREATE TEMPORARY TABLE MyTemporaryTable ( columnName varchar(100) );
set breaker = 0;
while (breaker < 2000) && (length(inputString) > 1) do
-- Iterate looking for the delimiter, add rows to temporary table.
set breaker = breaker + 1;
set pos = INSTR(inputString, '|');
set item = LEFT(inputString, pos - 1);
set inputString = substring(inputString, pos + 1);
insert into MyTemporaryTable values(item);
end while;
Например, ввод для этого кода может быть строкой Apple|Banana|Orange
. MyTemporaryTable
будет заполняться тремя строками, содержащими строки Apple
, Banana
и Orange
соответственно.
Я думал, что медленная скорость обработки строк сделает этот подход бесполезным, но он достаточно быстр (всего лишь часть секунды для массива 1000 записей).
Надеюсь, это поможет кому-то.
Ответ 7
Это моделирует массив символов, но вы можете подставить SUBSTR для ELT для имитации массива строк
declare t_tipos varchar(255) default 'ABCDE';
declare t_actual char(1);
declare t_indice integer default 1;
while t_indice<length(t_tipos)+1 do
set t_actual=SUBSTR(t_tipos,t_indice,1);
select t_actual;
set t_indice=t_indice+1;
end while;