web-dev-qa-db-fra.com

Passer un tableau à la routine stockée MySQL

Je dois passer un tableau de chaînes en tant que paramètre à une routine stockée MySQL. Le tableau peut être long et son nombre d'éléments n'est pas fixe. Je souhaite ensuite placer les valeurs de chaîne dans une table en mémoire avec une colonne afin de pouvoir utiliser les données. Je ne sais pas si cela peut être fait avec MySQL. Peut-être que des solutions de contournement sont nécessaires.

Par exemple, j'ai les valeurs de chaîne:

Banana, Apple, Orange

Maintenant, je veux obtenir des données sur ces fruits à partir de ma table MySQL Fruits. Pseudo code:

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 vous permet d'utiliser le type de données TEXT et de soumettre le tableau en tant que chaîne XML, en créant rapidement le tableau en mémoire. Cependant, je ne pense pas que cette technique soit possible dans MySQL.

Toute aide sur la façon de le faire serait appréciée!

50
Gruber

Vous pouvez passer une chaîne avec votre liste et utiliser un instructions préparées pour exécuter une requête, par exemple. -

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 ;

Comment utiliser:

SET @fruitArray = '\'Apple\',\'banana\'';
CALL GetFruits(@fruitArray);
58
Devart

Utilisez simplement FIND_IN_SET comme ça:

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2

alors tu peux faire:

select * from Fruits where FIND_IN_SET(fruit, fruitArray) > 0
29
Sagiv Ofek

Cela m’aide à le faire à condition d’espérer que cela vous aidera.

CREATE  PROCEDURE `test`(IN Array_String VARCHAR(100))
BEGIN
    SELECT * FROM Table_Name
    WHERE FIND_IN_SET(field_name_to_search, Array_String);

END//;

Appel:

 call test('3,2,1');
18
Raj

Utilisez une jointure avec une table temporaire. Vous n'avez pas besoin de passer des tables temporaires à des fonctions, elles sont globales .

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
9
bobobobo

Si vous ne voulez pas utiliser de tables temporaires, voici une chaîne divisée comme une fonction que vous pouvez utiliser.

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) renvoie le premier n
  • SUBSTRING_INDEX(string, delim, -1) renvoie le dernier seulement
  • REGEXP '((delim).*){n}' vérifie s'il y a n délimiteurs (c'est-à-dire que vous êtes dans les limites)
3
KCD

J'ai mis au point une solution peu pratique mais fonctionnelle à mon problème. Cela fonctionne pour un tableau unidimensionnel (plus de dimensions seraient délicates) et une entrée qui rentre dans un varchar:

  declare pos int;           -- Keeping track of the next item's 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;

Par exemple, l'entrée pour ce code pourrait être la chaîne Apple|Banana|Orange. MyTemporaryTable sera peuplé de trois lignes contenant les chaînes Apple, Banana et Orange respectivement.

Je pensais que la lenteur de la gestion des chaînes rendrait cette approche inutile, mais elle était assez rapide (une fraction de seconde pour un tableau de 1 000 entrées).

J'espère que ça aide quelqu'un.

3
Gruber

Ceci simule un tableau de caractères mais vous pouvez remplacer SUBSTR par ELT pour simuler un tableau de chaînes.

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;
1
pvilas