Подтвердить что ты не робот

Передача массива в 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.

Любая помощь в том, как это сделать, будет оценена по достоинству!

4b9b3361

Ответ 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;