Wie kann ich eine Array-Variable in MySQL simulieren?

87

Es scheint, dass MySQL keine Array-Variablen hat. Was soll ich stattdessen verwenden?


Es scheinen zwei Alternativen vorgeschlagen zu werden: Skalare vom Set-Typ und temporäre Tabellen . Die Frage, die ich verlinkt habe, deutet auf die erstere hin. Aber ist es eine gute Praxis, diese anstelle von Array-Variablen zu verwenden? Wenn ich alternativ zu Mengen gehe, was wäre die satzbasierte Redewendung foreach?

einpoklum
quelle
2
Verwenden Sie ELT.
Pacerier
1
@Pacerier: Können Sie auf eine ausführlichere Diskussion über ELT verweisen, vielleicht mit einem längeren Beispiel?
Einpoklum

Antworten:

73

Nun, ich habe temporäre Tabellen anstelle von Array-Variablen verwendet. Nicht die beste Lösung, aber es funktioniert.

Beachten Sie, dass Sie ihre Felder nicht formal definieren müssen, sondern sie nur mit SELECT erstellen:

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

(Siehe auch Temporäre Tabelle aus select-Anweisung erstellen, ohne Tabelle erstellen zu verwenden .)

einpoklum
quelle
1
Ohhh: o Ich wusste nicht, dass SQL das hat !! Die Tabellen sind nur für den Umfang aller ausgeführten Abfragen aktiv. ORDENTLICH!
iGbanam
2
@Yasky, vorausgesetzt, Sie verwenden die Verbindung nicht wieder. Denn in der Tat wird es für die gesamte Sitzung dauern .
Pacerier
Und Sie können eine temporäre Tabelle nicht wiederverwenden. Es ist also nicht sehr nützlich.
John
4
@ John: Ja, gut, du kannst es wiederverwenden, aber nicht in derselben Abfrage.
Einpoklum
44

Sie können dies in MySQL mit WHILEloop erreichen:

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;

BEARBEITEN: Alternativ können Sie dies tun mit 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
quelle
4
Sind Schleifen nicht nur in gespeicherten Prozeduren möglich?
Einpoklum
2
Ja, richtig, es ist innerhalb gespeicherter Prozeduren, Funktionen und Trigger möglich.
Omesh
1
Daher kann ich den von Ihnen angegebenen Code nicht verwenden. Ich benötige etwas, das allgemeiner anwendbar ist.
Einpoklum
Sie können eine gespeicherte Beispielprozedur und CALLdiese schreiben .
Omesh
1
Ich denke nicht, dass Arrays benötigt werden. Sie können dies einfach mit temporären Tabellen oder UNION ALLohne Prozedur tun .
Omesh
26

Versuchen Sie es mit der Funktion FIND_IN_SET () von MySql, z

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

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

Hinweis: Sie müssen die Variable SET in StoredProcedure nicht festlegen, wenn Sie Parameter mit CSV-Werten übergeben.

Himalaya Garg
quelle
Beachten
Nemo
18

Heutzutage wäre die Verwendung eines JSON-Arrays eine offensichtliche Antwort.

Da dies eine alte, aber immer noch relevante Frage ist, habe ich ein kurzes Beispiel erstellt. JSON-Funktionen sind seit mySQL 5.7.x / MariaDB 10.2.3 verfügbar

Ich bevorzuge diese Lösung gegenüber ELT (), da sie eher einem Array ähnelt und dieses 'Array' im Code wiederverwendet werden kann.

Aber seien Sie vorsichtig: Es (JSON) ist sicherlich viel langsamer als die Verwendung einer temporären Tabelle. Es ist einfach praktischer. imo.

So verwenden Sie ein JSON-Array:

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

Und hier ein kleines Beispiel, um zu zeigen, wie es in einer Funktion / Prozedur funktioniert:

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();
SeparateReality
quelle
Wollen Sie damit sagen, dass ELT langsamer oder JSON langsamer ist?
Kanagavelu Sugumar
2
@ Kanagavelu Sugumar: Zum Zeitpunkt des Schreibens ist JSON definitiv langsamer. Ich habe die Antwort bearbeitet, um das klarer zu machen.
SeparateReality
15

Sie kennen die Arrays nicht, aber es gibt eine Möglichkeit, durch Kommas getrennte Listen in einer normalen VARCHAR-Spalte zu speichern.

Und wenn Sie etwas in dieser Liste finden müssen, können Sie die Funktion FIND_IN_SET () verwenden.

Wurmhit
quelle
Wenn ich eine Teilmenge in einer Menge finden möchte, gibt es eine Möglichkeit?
Akshay Vishnoi
Es tut uns leid! Ich bin mir nicht sicher, ob es möglich ist.
Wurmhit
Sie haben die beste Lösung
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
quelle
2
Bitte erläutern Sie, wie dieser Code verwendet werden soll und wie er die Frage beantwortet.
Einpoklum
Wie hier machen Sie eine einfache Prozedur, die eins nach dem anderen Element dieser bestimmten Zeichenfolge ergibt, die als Array in Oracle fungiert.
Sagar Gangwal
Orakel? Diese Frage bezieht sich nicht auf Oracle. Es sieht auch so aus, als würden Sie ein Array innerhalb der Prozedur definieren.
Einpoklum
Bitte überprüfen Sie Syntex, es ist nur für MySQL
Sagar Gangwal
Verpassen Sie nicht das letzte Komma!
Eagle_Eye
4

Ich weiß, dass dies eine etwas späte Antwort ist, aber ich musste kürzlich ein ähnliches Problem lösen und dachte, dass dies für andere nützlich sein könnte.

Hintergrund

Betrachten Sie die folgende Tabelle mit dem Namen "mytable":

Starttisch

Das Problem bestand darin, nur die letzten 3 Datensätze zu behalten und alle älteren Datensätze zu löschen, deren System-ID = 1 ist (es könnten viele andere Datensätze in der Tabelle mit anderen System-ID-Werten vorhanden sein).

Es wäre gut, wenn Sie dies einfach mit der Anweisung tun könnten

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

Dies wird jedoch in MySQL noch nicht unterstützt und wenn Sie dies versuchen, erhalten Sie eine Fehlermeldung wie

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

Daher ist eine Problemumgehung erforderlich, bei der ein Array von Werten mithilfe einer Variablen an den IN-Selektor übergeben wird. Da Variablen jedoch einzelne Werte sein müssen, müsste ich ein Array simulieren . Der Trick besteht darin, das Array als durch Kommas getrennte Werteliste (Zeichenfolge) zu erstellen und diese der Variablen wie folgt zuzuweisen

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);

Das in @myvar gespeicherte Ergebnis ist

5,6,7

Als nächstes wird der Selektor FIND_IN_SET verwendet, um aus dem simulierten Array auszuwählen

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

Das kombinierte Endergebnis ist wie folgt:

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);

Mir ist bewusst, dass dies ein sehr spezifischer Fall ist. Es kann jedoch so geändert werden, dass es fast jedem anderen Fall entspricht, in dem eine Variable ein Array von Werten speichern muss.

Ich hoffe das hilft.

Clinton
quelle
3

Erstellen Sie möglicherweise eine temporäre Speichertabelle mit Spalten (Schlüssel, Wert), wenn Sie assoziative Arrays möchten. Eine Speichertabelle zu haben, kommt Arrays in MySQL am nächsten

Pavle Lekic
quelle
Ähm, ich möchte keine assoziativen Arrays, nur Arrays.
Einpoklum
Sie können eine temporäre Speichertabelle mit nur einer Spalte verwenden und dann die Werte mit Cursorn durchlaufen, was der Verwendung von Arrays und for / while-Schleifen in einer nicht deklarativen Programmiersprache am nächsten kommt
Pavle Lekic
Die Sprache hat tatsächlich diese Funktion, dh es gibt keinen syntaktischen Grund, warum Sie nicht in der Lage sein sollten, einen Vektor in eine Variable auszuwählen, so wie Sie einen Skalar darin auswählen.
Einpoklum
3

So habe ich es gemacht.

Zuerst habe ich eine Funktion erstellt, die prüft, ob ein Long / Integer / Whatever-Wert in einer durch Kommas getrennten Werteliste enthalten ist:

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;

Jetzt können Sie in einer durch Kommas getrennten Liste von IDs wie folgt nach einer ID suchen:

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

Und Sie können diese Funktion in einer WHERE-Klausel wie folgt verwenden:

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

Dies war die einzige Möglichkeit, einen "Array" -Parameter an ein PROCEDURE zu übergeben.

chuckedw
quelle
2

Ist der Sinn von Arrays nicht effizient? Wenn Sie nur Werte durchlaufen, ist ein Cursor auf einer temporären (oder permanenten) Tabelle meiner Meinung nach sinnvoller als das Suchen nach Kommas, oder? Auch sauberer. Suchen Sie nach "mysql DECLARE CURSOR".

Für den wahlfreien Zugriff eine temporäre Tabelle mit numerisch indiziertem Primärschlüssel. Leider ist der schnellste Zugriff eine Hash-Tabelle, kein echter Direktzugriff.

Amaigus
quelle
Dies ist ein Kommentar, keine Antwort. Ich habe nicht angegeben, dass ich das mit dem Array machen möchte.
Einpoklum
2

Ich bin überrascht, dass in keiner der Antworten ELT / FIELD erwähnt wird.

ELT / FIELD funktioniert einem Array sehr ähnlich, insbesondere wenn Sie statische Daten haben.

FIND_IN_SET funktioniert ebenfalls ähnlich, verfügt jedoch nicht über eine integrierte Komplementärfunktion, aber es ist einfach genug, eine zu schreiben.

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
quelle
1

Dies funktioniert gut für eine Liste von Werten:

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
quelle
1

Beide Versionen mit Sets haben bei mir nicht funktioniert (getestet mit MySQL 5.5). Die Funktion ELT () gibt den gesamten Satz zurück. Da die WHILE-Anweisung nur im PROCEDURE-Kontext verfügbar ist, habe ich sie meiner Lösung hinzugefügt:

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__;

Um ehrlich zu sein, denke ich nicht, dass dies eine gute Praxis ist. Auch wenn es wirklich notwendig ist, ist dies kaum lesbar und ziemlich langsam.

jmmeier
quelle
1

Ein anderer Weg, um das gleiche Problem zu sehen. Hoffe hilfreich

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
quelle
Eigentlich ist nicht klar, was Sie hier sagen. Diese Frage von vor 7 Jahren hat mehrere relevante Antworten. Entfernen Sie Ihre Antwort oder erklären Sie, was Sie uns direkt / allgemein mitteilen möchten, anstatt anhand eines Beispiels.
Einpoklum
0

In der MYSQL-Version nach 5.7.x können Sie den JSON-Typ zum Speichern eines Arrays verwenden. Sie können den Wert eines Arrays über einen Schlüssel über MYSQL abrufen.

Nick verdammt
quelle
7
Können Sie ein Beispiel geben, wie ich das machen würde?
Einpoklum
0

Inspiriert von der Funktion ELT (Indexnummer, Zeichenfolge1, Zeichenfolge2, Zeichenfolge3,…) funktioniert das folgende Beispiel meines Erachtens als Array-Beispiel:

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

Hoffe es hilft.

Edward
quelle
0

Hier ist ein Beispiel für MySQL zum Durchlaufen einer durch Kommas getrennten Zeichenfolge.

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;

Dies verwendet die get_from_delimiter_split_stringhier definierte Funktion: https://stackoverflow.com/a/59666211/3068233

Ulad Kasach
quelle
Kommagetrennte Zeichenfolgen wurden bereits vor Jahren vorgeschlagen.
Einpoklum
@einpoklum yep - und hier ist eine andere Art der Interaktion mit ihnen
Ulad Kasach
0

Ist eine Array-Variable wirklich notwendig?

Ich frage, weil ich ursprünglich hier gelandet bin und ein Array als MySQL-Tabellenvariable hinzufügen möchte. Ich war relativ neu im Datenbankdesign und versuchte zu überlegen, wie ich es in einer typischen Programmiersprache machen würde.

Datenbanken sind jedoch unterschiedlich. Ich dachte, ich wollte ein Array als Variable, aber es stellt sich heraus, dass dies keine übliche MySQL-Datenbankpraxis ist.

Standardverfahren

Die alternative Lösung zu Arrays besteht darin, eine zusätzliche Tabelle hinzuzufügen und dann mit einem Fremdschlüssel auf Ihre ursprüngliche Tabelle zu verweisen.

Stellen wir uns als Beispiel eine Anwendung vor, die alle Artikel erfasst, die jede Person in einem Haushalt im Geschäft kaufen möchte.

Die Befehle zum Erstellen der Tabelle, die ich mir ursprünglich vorgestellt hatte, hätten ungefähr so ​​ausgesehen:

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

Ich denke, ich habe mir buy_list als eine durch Kommas getrennte Folge von Gegenständen oder so etwas vorgestellt.

Aber MySQL hat kein Array-Typ-Feld, also brauchte ich wirklich so etwas:

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)
);

Hier definieren wir eine Einschränkung mit dem Namen fk_person. Es heißt, dass das Feld "Person" in BuyList ein Fremdschlüssel ist. Mit anderen Worten, es ist ein Primärschlüssel in einer anderen Tabelle, insbesondere das Feld 'Name' in der Personentabelle, was in REFERENZEN angegeben ist.

Wir haben auch die Kombination von Person und Gegenstand als Primärschlüssel definiert, aber technisch ist dies nicht erforderlich.

Wenn Sie alle Elemente in der Liste einer Person abrufen möchten, können Sie diese Abfrage ausführen:

SELECT item FROM BuyList WHERE person='John';

Dies gibt Ihnen alle Elemente auf Johns Liste. Keine Arrays notwendig!

Kraftydevil
quelle
Meine akzeptierte Lösung besteht darin, eine temporäre Tabelle zu verwenden.
Einpoklum
Natürlich. Ich habe diese Antwort dann für alle wie mich eingefügt, die auf dieser Seite nach einer Möglichkeit gesucht haben, einen Array-Typ zu erstellen - der zunächst nicht verstand, warum Arrays in MySQL kein Typ sind. Es ist beabsichtigt, wie es scheint. Der allgemeine Fall wurde hier nicht dargestellt, daher habe ich das aufgenommen, was ich gelernt habe, damit andere verstehen, dass Arrays normalerweise nicht benötigt werden. Ich erwarte nicht, dass Sie meine Antwort auswählen. Dies hängt vom Anwendungsfall ab. Sie haben Ihre akzeptierte Antwort für einen bestimmten Anwendungsfall und ich gebe diese Antwort für den allgemeinen Anwendungsfall.
Kraftydevil
0

Wenn wir so einen Tisch haben

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

und die Array-Tabelle:

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 |

Wir können die Zeilen der zweiten Tabelle als ein Array mit der CONCAT-Funktion auswählen:

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
quelle
Duplikat von Clintons Antwort, denke ich.
Einpoklum
-2

Ich denke, ich kann diese Antwort verbessern. Versuche dies:

Der Parameter 'Streiche' ist eine CSV. dh. '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;

Diese Methode verkürzt die gesuchte Zeichenfolge von CSV-Werten mit jeder Iteration der Schleife zunehmend, was meiner Meinung nach für die Optimierung besser wäre.

user2288580
quelle
Was ist "diese Antwort", auf die Sie sich beziehen? Außerdem erhalten Sie keine CSV-Datei.
Einpoklum
Ich bezog mich nicht auf eine CSV-Datei, sondern auf einen CSV-Wert wie '1,2,3,4 ... etc'
user2288580
-2

Ich würde so etwas für mehrere Sammlungen versuchen. Ich bin ein MySQL-Anfänger. Entschuldigung für die Funktionsnamen, konnte mich nicht entscheiden, welche Namen am besten sind.

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
quelle
Ich denke, ich verstehe, was Sie vorschlagen, aber das ist ziemlich unhandlich und wahrscheinlich auch unglaublich langsam ...
einpoklum
Ich kann es nicht unterstützen oder ablehnen, ohne es zu testen. Dies ist im Grunde eine Primärschlüssel-Suche und Einfügung in eine temporäre Tabelle (oder eine normale Tabelle). Ich werde es verwenden, bis ich auf Probleme stoße oder einen besseren Weg finde. Aber ich mache seltsame Dinge wie das vollständige Schreiben von Compilern und Spielen in Oracle PL / SQL.
Dave
-2

Anstatt Daten als Array oder nur in einer Zeile zu speichern, sollten Sie für jeden empfangenen Wert unterschiedliche Zeilen erstellen. Dies macht es viel einfacher zu verstehen, als alles zusammenzufügen.

Chirag Mathur
quelle
Bitte teilen Sie, wie das geht
Nico Haase
-5

Haben Sie versucht, PHPs serialize () zu verwenden? Auf diese Weise können Sie den Inhalt des Arrays einer Variablen in einer Zeichenfolge speichern, die PHP versteht und für die Datenbank sicher ist (vorausgesetzt, Sie haben sie zuerst maskiert).

$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());

Sie können dies auch ohne nummeriertes Array tun

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

oder

$array3 = array(
    'somethingNew'
);
Magictallguy
quelle
7
Ich arbeite nicht mit PHP, das ist also für mich nicht wirklich relevant.
Einpoklum
1
Verwenden Sie JSON anstelle von Serialisierung. Es ist allgemeiner und sprachunabhängiger.
Rick James