Comment puis-je simuler une variable de tableau dans MySQL?

91

Il semble que MySQL n'a pas de variables de tableau. Que dois-je utiliser à la place?


Il semble y avoir deux alternatives suggérées: un scalaire de type ensemble et des tables temporaires . La question à laquelle j'ai lié suggère la première. Mais est-ce une bonne pratique de les utiliser au lieu de variables de tableau? Sinon, si j'utilise des ensembles, quel serait l'équivalent de l'idiome basé sur les ensembles foreach?

einpoklum
la source
2
Utilisez ELT.
Pacerier
1
@Pacerier: Pouvez-vous créer un lien vers une discussion plus verbeuse sur ELT, peut-être avec un exemple plus long?
einpoklum

Réponses:

77

Eh bien, j'ai utilisé des tables temporaires au lieu de variables de tableau. Ce n'est pas la meilleure solution, mais cela fonctionne.

Notez que vous n'avez pas besoin de définir formellement leurs champs, créez-les simplement à l'aide d'un SELECT:

CREATE TEMPORARY TABLE IF NOT EXISTS my_temp_table
SELECT first_name FROM people WHERE last_name = 'Smith';

(Voir aussi Créer une table temporaire à partir de l'instruction select sans utiliser Create Table .)

einpoklum
la source
1
Ohhh: o Je ne savais pas que SQL avait ça !! Les tables ne sont actives que pour la portée de toutes les requêtes en cours d'exécution. SOIGNÉ!
iGbanam
2
@Yasky, à condition de ne pas réutiliser la connexion. Parce qu'en effet cela durera toute la session.
Pacerier
Et vous ne pouvez pas réutiliser une table temporaire. Ce n'est donc pas très utile.
John
4
@John: Ouais, eh bien, vous pouvez le réutiliser, mais pas dans la même requête.
einpoklum
46

Vous pouvez y parvenir dans MySQL en utilisant la WHILEboucle:

SET @myArrayOfValue = '2,5,2,23,6,';

WHILE (LOCATE(',', @myArrayOfValue) > 0)
DO
    SET @value = ELT(1, @myArrayOfValue);
    SET @myArrayOfValue= SUBSTRING(@myArrayOfValue, LOCATE(',',@myArrayOfValue) + 1);

    INSERT INTO `EXEMPLE` VALUES(@value, 'hello');
END WHILE;

EDIT: Vous pouvez également le faire en utilisant UNION ALL:

INSERT INTO `EXEMPLE`
(
 `value`, `message`
)
(
 SELECT 2 AS `value`, 'hello' AS `message`
 UNION ALL
 SELECT 5 AS `value`, 'hello' AS `message`
 UNION ALL
 SELECT 2 AS `value`, 'hello' AS `message`
 UNION ALL
 ...
);
Omesh
la source
4
Les boucles ne sont-elles pas possibles uniquement dans les procédures stockées?
einpoklum
2
oui, c'est possible à l'intérieur des procédures stockées, des fonctions et des déclencheurs.
Omesh
1
Je ne peux donc pas utiliser le code que vous avez fourni ... J'ai besoin de quelque chose qui s'applique plus généralement.
einpoklum
Vous pouvez écrire un exemple de procédure stockée et CALLcela.
Omesh
1
Je ne pense pas que les tableaux soient nécessaires. Vous pouvez facilement le faire en utilisant des tables temporaires ou UNION ALLsans utiliser de procédure.
Omesh
28

Essayez d'utiliser la fonction FIND_IN_SET () de MySql par exemple

SET @c = 'xxx,yyy,zzz';

SELECT * from countries 
WHERE FIND_IN_SET(countryname,@c);

Remarque: vous n'avez pas à définir la variable dans StoredProcedure si vous transmettez des paramètres avec des valeurs CSV.

Himalaya Garg
la source
Méfiez-vous des limites de longueur, qui peuvent être assez faibles: stackoverflow.com/q/2567000/1333493
Nemo
19

De nos jours, l'utilisation d'un tableau JSON serait une réponse évidente.

Comme il s'agit d'une question ancienne mais toujours pertinente, j'ai produit un court exemple. Les fonctions JSON sont disponibles depuis mySQL 5.7.x / MariaDB 10.2.3

Je préfère cette solution à ELT () car c'est vraiment plus comme un tableau et ce «tableau» peut être réutilisé dans le code.

Mais attention: il (JSON) est certainement beaucoup plus lent que l'utilisation d'une table temporaire. C'est juste plus pratique. imo.

Voici comment utiliser un tableau JSON:

SET @myjson = '["gmail.com","mail.ru","arcor.de","gmx.de","t-online.de",
                "web.de","googlemail.com","freenet.de","yahoo.de","gmx.net",
                "me.com","bluewin.ch","hotmail.com","hotmail.de","live.de",
                "icloud.com","hotmail.co.uk","yahoo.co.jp","yandex.ru"]';

SELECT JSON_LENGTH(@myjson);
-- result: 19

SELECT JSON_VALUE(@myjson, '$[0]');
-- result: gmail.com

Et voici un petit exemple pour montrer comment cela fonctionne dans une fonction / procédure:

DELIMITER //
CREATE OR REPLACE FUNCTION example() RETURNS varchar(1000) DETERMINISTIC
BEGIN
  DECLARE _result varchar(1000) DEFAULT '';
  DECLARE _counter INT DEFAULT 0;
  DECLARE _value varchar(50);

  SET @myjson = '["gmail.com","mail.ru","arcor.de","gmx.de","t-online.de",
                "web.de","googlemail.com","freenet.de","yahoo.de","gmx.net",
                "me.com","bluewin.ch","hotmail.com","hotmail.de","live.de",
                "icloud.com","hotmail.co.uk","yahoo.co.jp","yandex.ru"]';

  WHILE _counter < JSON_LENGTH(@myjson) DO
    -- do whatever, e.g. add-up strings...
    SET _result = CONCAT(_result, _counter, '-', JSON_VALUE(@myjson, CONCAT('$[',_counter,']')), '#');

    SET _counter = _counter + 1;
  END WHILE;

  RETURN _result;
END //
DELIMITER ;

SELECT example();
SéparéRéalité
la source
Êtes-vous en train de dire que ELT est plus lent ou JSON est plus lent?
Kanagavelu Sugumar
2
@Kanagavelu Sugumar: Au moment d'écrire ces lignes, JSON est définitivement plus lent. J'ai modifié la réponse pour que cela soit plus clair.
SeparateReality
16

Je ne connais pas les tableaux, mais il existe un moyen de stocker des listes séparées par des virgules dans la colonne VARCHAR normale.

Et lorsque vous avez besoin de trouver quelque chose dans cette liste, vous pouvez utiliser la fonction FIND_IN_SET () .

wormhit
la source
Si je veux trouver un sous-ensemble dans un ensemble, y a-t-il un moyen?
Akshay Vishnoi
Pardon! Je ne suis pas sûr que ce soit possible.
wormhit
Vous avez la meilleure solution
Calvin
7
DELIMITER $$
CREATE DEFINER=`mysqldb`@`%` PROCEDURE `abc`()
BEGIN
  BEGIN 
    set @value :='11,2,3,1,'; 
    WHILE (LOCATE(',', @value) > 0) DO
      SET @V_DESIGNATION = SUBSTRING(@value,1, LOCATE(',',@value)-1); 
      SET @value = SUBSTRING(@value, LOCATE(',',@value) + 1); 
      select @V_DESIGNATION;
    END WHILE;
  END;
END$$
DELIMITER ;
Sagar Gangwal
la source
2
Veuillez expliquer comment ce code doit être utilisé et comment il répond à la question.
einpoklum le
Comme ici, vous faites une procédure simple qui donne un par un élément de cette chaîne particulière qui fonctionne comme un tableau dans oracle.
Sagar Gangwal
Oracle? Cette question ne concerne pas Oracle. En outre, il semble que vous définissiez un tableau dans la procédure.
einpoklum
Veuillez vérifier Syntex, c'est uniquement pour mysql
Sagar Gangwal
Ne manquez pas la dernière virgule!
Eagle_Eye
4

Je sais que c'est un peu une réponse tardive, mais j'ai récemment dû résoudre un problème similaire et j'ai pensé que cela pourrait être utile à d'autres.

Contexte

Considérez le tableau ci-dessous appelé «mytable»:

Table de départ

Le problème était de ne conserver que les 3 derniers enregistrements et de supprimer tous les enregistrements plus anciens dont l'ID système = 1 (il pourrait y avoir de nombreux autres enregistrements dans la table avec d'autres valeurs ID système)

Ce serait bien que vous puissiez le faire simplement en utilisant la déclaration

DELETE FROM mytable WHERE id IN (SELECT id FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3)

Cependant, cela n'est pas encore pris en charge dans MySQL et si vous essayez ceci, vous obtiendrez une erreur comme

...doesn't yet support 'LIMIT & IN/ALL/SOME subquery'

Une solution de contournement est donc nécessaire par laquelle un tableau de valeurs est passé au sélecteur IN à l'aide d'une variable. Cependant, comme les variables doivent être des valeurs uniques, je devrais simuler un tableau . L'astuce consiste à créer le tableau sous forme de liste de valeurs séparées par des virgules (chaîne) et à l'affecter à la variable comme suit

SET @myvar := (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);

Le résultat stocké dans @myvar est

5,6,7

Ensuite, le sélecteur FIND_IN_SET est utilisé pour sélectionner dans le tableau simulé

SELECT * FROM mytable WHERE FIND_IN_SET(id,@myvar);

Le résultat final combiné est le suivant:

SET @myvar := (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);
DELETE FROM mytable WHERE FIND_IN_SET(id,@myvar);

Je suis conscient qu'il s'agit d'un cas très particulier. Cependant, il peut être modifié pour convenir à n'importe quel autre cas où une variable doit stocker un tableau de valeurs.

J'espère que ca aide.

Clinton
la source
3

Peut-être créer une table mémoire temporaire avec des colonnes (clé, valeur) si vous voulez des tableaux associatifs. Avoir une table mémoire est la chose la plus proche d'avoir des tableaux dans mysql

Pavle Lekic
la source
Euh, je ne veux pas de tableaux associatifs, juste des tableaux.
einpoklum
vous pouvez utiliser une table de mémoire temporaire avec une seule colonne, puis parcourir les valeurs en utilisant des curseurs, c'est la chose la plus proche de l'utilisation de tableaux et de boucles for / while dans un langage de programmation non déclaratif
Pavle Lekic
Le langage a en fait cette fonctionnalité, c'est-à-dire qu'il n'y a aucune raison syntaxique pour laquelle vous ne devriez pas être en mesure de sélectionner un vecteur dans une variable comme vous y sélectionnez un scalaire.
einpoklum
3

Voici comment je l'ai fait.

Tout d'abord, j'ai créé une fonction qui vérifie si une valeur Long / Integer / quelle que soit la valeur se trouve dans une liste de valeurs séparées par des virgules:

CREATE DEFINER = 'root'@'localhost' FUNCTION `is_id_in_ids`(
        `strIDs` VARCHAR(255),
        `_id` BIGINT
    )
    RETURNS BIT(1)
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

  DECLARE strLen    INT DEFAULT 0;
  DECLARE subStrLen INT DEFAULT 0;
  DECLARE subs      VARCHAR(255);

  IF strIDs IS NULL THEN
    SET strIDs = '';
  END IF;

  do_this:
    LOOP
      SET strLen = LENGTH(strIDs);
      SET subs = SUBSTRING_INDEX(strIDs, ',', 1);

      if ( CAST(subs AS UNSIGNED) = _id ) THEN
        -- founded
        return(1);
      END IF;

      SET subStrLen = LENGTH(SUBSTRING_INDEX(strIDs, ',', 1));
      SET strIDs = MID(strIDs, subStrLen+2, strLen);

      IF strIDs = NULL or trim(strIds) = '' THEN
        LEAVE do_this;
      END IF;

  END LOOP do_this;

   -- not founded
  return(0);

END;

Vous pouvez maintenant rechercher un identifiant dans une liste d'identifiants séparés par des virgules, comme ceci:

select `is_id_in_ids`('1001,1002,1003',1002);

Et vous pouvez utiliser cette fonction dans une clause WHERE, comme ceci:

SELECT * FROM table1 WHERE `is_id_in_ids`('1001,1002,1003',table1_id);

C'était le seul moyen que j'ai trouvé pour passer un paramètre "array" à une PROCEDURE.

chuckedw
la source
2

Le but des tableaux n'est-il pas d'être efficace? Si vous ne faites que parcourir des valeurs, je pense qu'un curseur sur une table temporaire (ou permanente) a plus de sens que de chercher des virgules, non? Aussi plus propre. Recherchez "mysql DECLARE CURSOR".

Pour un accès aléatoire, une table temporaire avec une clé primaire indexée numériquement. Malheureusement, l'accès le plus rapide que vous obtiendrez est une table de hachage, pas un véritable accès aléatoire.

Amaigus
la source
Ceci est un commentaire, pas une réponse. Je n'ai pas indiqué que c'était ce que je voulais faire avec le tableau.
einpoklum du
2

Je suis surpris qu'aucune des réponses ne mentionne ELT / FIELD.

ELT / FIELD fonctionne très similaire à un tableau, surtout si vous avez des données statiques.

FIND_IN_SET fonctionne également de manière similaire mais n'a pas de fonction complémentaire intégrée mais il est assez facile d'en écrire une.

mysql> select elt(2,'AA','BB','CC');
+-----------------------+
| elt(2,'AA','BB','CC') |
+-----------------------+
| BB                    |
+-----------------------+
1 row in set (0.00 sec)

mysql> select field('BB','AA','BB','CC');
+----------------------------+
| field('BB','AA','BB','CC') |
+----------------------------+
|                          2 |
+----------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('BB','AA,BB,CC');
+------------------------------+
| find_in_set('BB','AA,BB,CC') |
+------------------------------+
|                            2 |
+------------------------------+
1 row in set (0.00 sec)

mysql>  SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('AA,BB,CC',',',2),',',-1);
+-----------------------------------------------------------+
| SUBSTRING_INDEX(SUBSTRING_INDEX('AA,BB,CC',',',2),',',-1) |
+-----------------------------------------------------------+
| BB                                                        |
+-----------------------------------------------------------+
1 row in set (0.01 sec)
Jongab
la source
1

Cela fonctionne bien pour la liste de valeurs:

SET @myArrayOfValue = '2,5,2,23,6,';

WHILE (LOCATE(',', @myArrayOfValue) > 0)
DO
SET @value = ELT(1, @myArrayOfValue);
    SET @STR = SUBSTRING(@myArrayOfValue, 1, LOCATE(',',@myArrayOfValue)-1);
    SET @myArrayOfValue = SUBSTRING(@myArrayOfValue, LOCATE(',', @myArrayOfValue) + 1);

    INSERT INTO `Demo` VALUES(@STR, 'hello');
END WHILE;
user2664904
la source
1

Les deux versions utilisant des ensembles ne fonctionnaient pas pour moi (testé avec MySQL 5.5). La fonction ELT () retourne l'ensemble complet. Étant donné que l'instruction WHILE n'est disponible que dans le contexte PROCEDURE, je l'ai ajoutée à ma solution:

DROP PROCEDURE IF EXISTS __main__;

DELIMITER $
CREATE PROCEDURE __main__()
BEGIN
    SET @myArrayOfValue = '2,5,2,23,6,';

    WHILE (LOCATE(',', @myArrayOfValue) > 0)
    DO
        SET @value = LEFT(@myArrayOfValue, LOCATE(',',@myArrayOfValue) - 1);    
        SET @myArrayOfValue = SUBSTRING(@myArrayOfValue, LOCATE(',',@myArrayOfValue) + 1);
    END WHILE;
END;
$
DELIMITER ;

CALL __main__;

Pour être honnête, je ne pense pas que ce soit une bonne pratique. Même si c'est vraiment nécessaire, c'est à peine lisible et assez lent.

jmmeier
la source
1

Une autre façon de voir le même problème. J'espère utile

DELIMITER $$
CREATE PROCEDURE ARR(v_value VARCHAR(100))
BEGIN

DECLARE v_tam VARCHAR(100);
DECLARE v_pos VARCHAR(100);

CREATE TEMPORARY TABLE IF NOT EXISTS split (split VARCHAR(50));

SET v_tam = (SELECT (LENGTH(v_value) - LENGTH(REPLACE(v_value,',',''))));
SET v_pos = 1;

WHILE (v_tam >= v_pos)
DO
    INSERT INTO split 
    SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(v_value,',',v_pos),',', -1);
    SET v_pos = v_pos + 1;
END WHILE;

SELECT * FROM split;

DROP TEMPORARY TABLE split;

END$$


CALL ARR('1006212,1006404,1003404,1006505,444,');
Walter Azevedo
la source
En fait, ce que vous dites ici n'est pas clair. Cette question d'il y a 7 ans a plusieurs réponses pertinentes. Envisagez de supprimer votre réponse ou d'expliquer ce que vous essayez de nous dire directement / généralement plutôt que par le biais d'un exemple.
einpoklum le
0

Dans la version MYSQL après 5.7.x, vous pouvez utiliser le type JSON pour stocker un tableau. Vous pouvez obtenir la valeur d'un tableau par une clé via MYSQL.

nick darn
la source
7
Pouvez-vous donner un exemple de la façon dont je ferais cela?
einpoklum le
0

Inspiré de la fonction ELT (numéro d'index, string1, string2, string3,…), je pense que l'exemple suivant fonctionne comme un exemple de tableau:

set @i := 1;
while @i <= 3
do
  insert into table(val) values (ELT(@i ,'val1','val2','val3'...));
set @i = @i + 1;
end while;

J'espère que cela aidera.

Edward
la source
0

Voici un exemple pour MySQL pour boucler une chaîne délimitée par des virgules.

DECLARE v_delimited_string_access_index INT;
DECLARE v_delimited_string_access_value VARCHAR(255);
DECLARE v_can_still_find_values_in_delimited_string BOOLEAN;

SET v_can_still_find_values_in_delimited_string = true;
SET v_delimited_string_access_index = 0;
WHILE (v_can_still_find_values_in_delimited_string) DO
  SET v_delimited_string_access_value = get_from_delimiter_split_string(in_array, ',', v_delimited_string_access_index); -- get value from string
  SET v_delimited_string_access_index = v_delimited_string_access_index + 1;
  IF (v_delimited_string_access_value = '') THEN
    SET v_can_still_find_values_in_delimited_string = false; -- no value at this index, stop looping
  ELSE
    -- DO WHAT YOU WANT WITH v_delimited_string_access_value HERE
  END IF;
END WHILE;

cela utilise la get_from_delimiter_split_stringfonction définie ici: https://stackoverflow.com/a/59666211/3068233

Ulad Kasach
la source
des chaînes délimitées par des virgules ont déjà été suggérées - il y a des années.
einpoklum
@einpoklum yep - et voici une autre façon d'interagir avec eux
Ulad Kasach
0

Une variable de tableau est-elle vraiment nécessaire?

Je demande parce que j'ai atterri ici à l'origine voulant ajouter un tableau en tant que variable de table MySQL. J'étais relativement nouveau dans la conception de bases de données et j'essayais de penser à la façon dont je le ferais dans un langage de programmation typique.

Mais les bases de données sont différentes. J'ai pensé je voulais un tableau comme variable, mais il s'avère que ce n'est tout simplement pas une pratique courante de base de données MySQL.

Pratique standard

La solution alternative aux tableaux consiste à ajouter une table supplémentaire, puis à référencer votre table d'origine avec une clé étrangère.

À titre d'exemple, imaginons une application qui garde la trace de tous les articles que chaque personne d'un ménage souhaite acheter au magasin.

Les commandes pour créer la table que j'avais initialement envisagées auraient ressemblé à ceci:

#doesn't work
CREATE TABLE Person(
  name VARCHAR(50) PRIMARY KEY
  buy_list ARRAY
);

Je pense que j'ai envisagé buy_list comme une chaîne d'éléments séparés par des virgules ou quelque chose comme ça.

Mais MySQL n'a pas de champ de type tableau, donc j'avais vraiment besoin de quelque chose comme ceci:

CREATE TABLE Person(
  name VARCHAR(50) PRIMARY KEY
);
CREATE TABLE BuyList(
  person VARCHAR(50),
  item VARCHAR(50),
  PRIMARY KEY (person, item),
  CONSTRAINT fk_person FOREIGN KEY (person) REFERENCES Person(name)
);

Ici, nous définissons une contrainte nommée fk_person. Il indique que le champ «personne» dans BuyList est une clé étrangère. En d'autres termes, il s'agit d'une clé primaire dans une autre table, en particulier le champ «nom» de la table Personne, ce que REFERENCES indique.

Nous avons également défini la combinaison de la personne et de l'élément comme étant la clé primaire, mais techniquement ce n'est pas nécessaire.

Enfin, si vous souhaitez obtenir tous les éléments de la liste d'une personne, vous pouvez exécuter cette requête:

SELECT item FROM BuyList WHERE person='John';

Cela vous donne tous les éléments de la liste de John. Aucun tableau nécessaire!

kraftydevil
la source
Ma solution acceptée est d'utiliser une table temporaire.
einpoklum
Bien sûr. J'ai ensuite inclus cette réponse pour toute personne comme moi qui est arrivée sur cette page à la recherche d'un moyen de créer un type de tableau - qui n'avait pas initialement compris pourquoi les tableaux ne sont pas un type dans MySQL. C'est par conception, semble-t-il. Le cas général n'était pas représenté ici, j'ai donc inclus ce que j'ai appris pour que les autres comprennent que les tableaux ne sont généralement pas nécessaires. Je ne m'attends pas à ce que vous choisissiez ma réponse. Cela dépend du cas d'utilisation. Vous avez votre réponse acceptée pour un cas d'utilisation spécifique et je fournis cette réponse pour le cas d'utilisation général.
kraftydevil
0

Si nous avons une table comme celle-là

mysql> select * from user_mail;
+------------+-------+
| email      | user | 
+------------+-------+-
| email1@gmail |     1 | 
| email2@gmail |     2 |
+------------+-------+--------+------------+

et la table de tableau:

mysql> select * from user_mail_array;
+------------+-------+-------------+
| email      | user | preferences |
+------------+-------+-------------+
| email1@gmail |     1 |           1 |
| email1@gmail |     1 |           2 |
| email1@gmail |     1 |           3 |
| email1@gmail |     1 |           4 |
| email2@gmail |     2 |           5 |
| email2@gmail |     2 |           6 |

Nous pouvons sélectionner les lignes de la deuxième table comme un tableau avec la fonction CONCAT:

mysql> SELECT t1.*, GROUP_CONCAT(t2.preferences) AS preferences
     FROM user_mail t1,user_mail_array t2
       where t1.email=t2.email and t1.user=t2.user
     GROUP BY t1.email,t1.user;

+------------+-------+--------+------------+-------------+
| email      | user | preferences |
+------------+-------+--------+------------+-------------+
|email1@gmail |     1 | 1,3,2,4     |
|email2@gmail |     2 | 5,6         |
+------------+-------+--------+------------+-------------+
aitor
la source
Duplication de la réponse de Clinton, je pense.
einpoklum
-2

Je pense que je peux améliorer cette réponse. Essaye ça:

Le paramètre «Pranks» est un CSV. c'est à dire. «1,2,3,4 ..... etc»

CREATE PROCEDURE AddRanks(
IN Pranks TEXT
)
BEGIN
  DECLARE VCounter INTEGER;
  DECLARE VStringToAdd VARCHAR(50);
  SET VCounter = 0;
  START TRANSACTION;
  REPEAT
    SET VStringToAdd = (SELECT TRIM(SUBSTRING_INDEX(Pranks, ',', 1)));
    SET Pranks = (SELECT RIGHT(Pranks, TRIM(LENGTH(Pranks) - LENGTH(SUBSTRING_INDEX(Pranks, ',', 1))-1)));
    INSERT INTO tbl_rank_names(rank)
    VALUES(VStringToAdd);
    SET VCounter = VCounter + 1;
  UNTIL (Pranks = '')
  END REPEAT;
  SELECT VCounter AS 'Records added';
  COMMIT;
END;

Cette méthode raccourcit progressivement la chaîne de valeurs CSV recherchée à chaque itération de la boucle, ce qui, je pense, serait préférable pour l'optimisation.

user2288580
la source
De quelle «réponse» parlez-vous? De plus, vous ne disposez pas d'un fichier CSV.
einpoklum
Je ne faisais pas référence à un fichier CSV, je faisais référence à une valeur CSV telle que '1,2,3,4 ... etc'
user2288580
-2

J'essaierais quelque chose comme ça pour plusieurs collections. Je suis un débutant MySQL. Désolé pour les noms de fonction, je n'ai pas pu décider quels noms seraient les meilleurs.

delimiter //

drop  procedure init_
//
create procedure init_()
begin
  CREATE TEMPORARY TABLE if not exists 
    val_store(  
    realm  varchar(30) 
    ,  id  varchar(30) 
    ,  val   varchar(255) 
    ,  primary key ( realm , id )
    );
end;
//

drop function if exists get_
//
create function get_( p_realm varchar(30) , p_id varchar(30) )
  returns varchar(255)
  reads sql data
begin 
  declare ret_val varchar(255);
  declare continue handler for 1146 set ret_val = null;
  select val into ret_val from val_store where id = p_id;
  return ret_val;
end;
//

drop procedure if exists set_
//
create procedure set_( p_realm varchar(30) , p_id varchar(30) , p_val varchar(255) )
begin
  call init_(); 
  insert into val_store (realm,id,val) values (p_realm , p_id , p_val) on duplicate key update val = p_val;
end;
//

drop   procedure if exists remove_
//
create procedure remove_( p_realm varchar(30) , p_id varchar(30) )
begin
  call init_();
  delete from val_store where realm = p_realm and id = p_id;
end;
//

drop   procedure if exists erase_
//
create procedure erase_( p_realm varchar(30) ) 
begin
  call init_();
  delete from val_store where realm = p_realm;
end;
//

call set_('my_array_table_name','my_key','my_value');

select get_('my_array_table_name','my_key');
Dave
la source
Je pense que je comprends ce que vous suggérez, mais c'est assez difficile à manier et probablement aussi incroyablement lent ...
einpoklum
Je ne peux pas l'approuver ou le rejeter sans le tester. Il s'agit essentiellement d'une recherche et d'une insertion de clé primaire sur une table temporaire (ou table normale). Je vais l'utiliser jusqu'à ce que je rencontre des problèmes ou que je trouve un meilleur moyen; mais je fais des choses bizarres comme écrire des compilateurs et des jeux complètement dans Oracle PL / SQL.
Dave
-2

Plutôt que d'enregistrer les données sous forme de tableau ou sur une seule ligne, vous devez créer des lignes différentes pour chaque valeur reçue. Cela rendra les choses beaucoup plus simples à comprendre plutôt que de tout rassembler.

chirag mathur
la source
Veuillez partager comment faire
Nico Haase le
-5

Avez-vous essayé d'utiliser serialize () de PHP? Cela vous permet de stocker le contenu du tableau d'une variable dans une chaîne que PHP comprend et est sans danger pour la base de données (en supposant que vous l'ayez d'abord échappé).

$array = array(
    1 => 'some data',
    2 => 'some more'
);

//Assuming you're already connected to the database
$sql = sprintf("INSERT INTO `yourTable` (`rowID`, `rowContent`) VALUES (NULL, '%s')"
     ,  serialize(mysql_real_escape_string($array, $dbConnection)));
mysql_query($sql, $dbConnection) or die(mysql_error());

Vous pouvez également faire exactement la même chose sans tableau numéroté

$array2 = array(
    'something' => 'something else'
);

ou

$array3 = array(
    'somethingNew'
);
Magictallguy
la source
7
Je ne travaille pas avec PHP, donc ce n'est pas vraiment pertinent pour moi.
einpoklum
1
Utilisez JSON au lieu de sérialiser. Il est plus générique et indépendant de la langue.
Rick James