it-swarm.com.de

Wie speichere ich Arrays in MySQL?

Ich habe zwei Tabellen in MySQL. Tabelle Person hat die folgenden Spalten:

id | name | fruits

Die fruits -Spalte kann null oder ein Array von Zeichenfolgen wie ("Apple", "Orange", "Banane") oder ("Erdbeere") usw. enthalten. Die zweite Tabelle ist "Table Fruit" und enthält Folgendes drei Spalten:

____________________________
fruit_name | color  | price
____________________________
Apple      | red    | 2
____________________________
orange     | orange | 3
____________________________
...,...

Wie sollte ich also die fruits -Spalte in der ersten Tabelle so gestalten, dass sie ein Array von Zeichenfolgen enthält, die Werte aus dem fruit_name Spalte in der zweiten Tabelle? Wie soll ich das tun, da MySQL keinen Array-Datentyp hat?

89
tonga

Der richtige Weg, dies zu tun, besteht darin, mehrere Tabellen und JOIN diese in Ihren Abfragen zu verwenden.

Zum Beispiel:

CREATE TABLE person (
`id` INT NOT NULL PRIMARY KEY,
`name` VARCHAR(50)
);

CREATE TABLE fruits (
`fruit_name` VARCHAR(20) NOT NULL PRIMARY KEY,
`color` VARCHAR(20),
`price` INT
);

CREATE TABLE person_fruit (
`person_id` INT NOT NULL,
`fruit_name` VARCHAR(20) NOT NULL,
PRIMARY KEY(`person_id`, `fruit_name`)
);

Das person_fruit Tabelle enthält eine Zeile für jede Frucht, der eine Person zugeordnet ist, und verknüpft effektiv die Tabellen person und fruits miteinander, I.E.

1 | "banana"
1 | "Apple"
1 | "orange"
2 | "straberry"
2 | "banana"
2 | "Apple"

Wenn Sie eine Person und alle ihre Früchte abrufen möchten, können Sie Folgendes tun:

SELECT p.*, f.*
FROM person p
INNER JOIN person_fruit pf
ON pf.person_id = p.id
INNER JOIN fruits f
ON f.fruit_name = pf.fruit_name
136
Bad Wolf

Der Grund dafür, dass es in SQL keine Arrays gibt, ist, dass die meisten Leute es nicht wirklich brauchen. Relationale Datenbanken (SQL ist genau das) arbeiten mit Relationen. In den meisten Fällen ist es am besten, wenn Sie jedem "Informationsbit" eine Tabellenzeile zuweisen. Wenn du zum Beispiel denkst, "Ich möchte hier eine Liste mit Dingen", erstelle stattdessen eine neue Tabelle, indem du die Zeile in einer Tabelle mit der Zeile in einer anderen Tabelle verbindest. Auf diese Weise können Sie M: N-Beziehungen darstellen. Ein weiterer Vorteil ist, dass diese Links die Zeile mit dem verknüpften Element nicht überladen. Und die Datenbank kann diese Zeilen indizieren. Arrays werden normalerweise nicht indiziert.

Wenn Sie keine relationalen Datenbanken benötigen, können Sie z. ein Schlüsselwertspeicher.

Lesen Sie über Datenbanknormalisierung , bitte. Die goldene Regel lautet: "[Jeder] Nichtschlüssel [Attribut] muss eine Tatsache über den Schlüssel, den gesamten Schlüssel und nichts als den Schlüssel liefern." Ein Array macht zu viel. Es hat mehrere Fakten und speichert die Reihenfolge (die nicht mit der Beziehung selbst zusammenhängt). Und die Leistung ist schlecht (so).

Stellen Sie sich vor, Sie haben einen Personentisch und einen Tisch mit Anrufen von Personen. Jetzt können Sie für jede Personenreihe eine Liste seiner Telefonanrufe erstellen. Aber jeder Mensch hat viele andere Beziehungen zu vielen anderen Dingen. Bedeutet das, dass meine Personentabelle ein Array für jede einzelne Sache enthalten sollte, mit der er verbunden ist? Nein, das ist kein Attribut der Person selbst.

[1]: Es ist in Ordnung, wenn die Verknüpfungstabelle nur zwei Spalten enthält (die Primärschlüssel aus jeder Tabelle)! Wenn die Beziehung selbst zusätzliche Attribute hat, sollten sie in dieser Tabelle als Spalten dargestellt werden.

50
Janus Troelsen

MySQL 5.7 bietet jetzt einen JSON-Datentyp . Dieser neue Datentyp bietet eine bequeme neue Möglichkeit zum Speichern komplexer Daten: Listen, Wörterbücher usw.

Allerdings ordnen Rays Datenbanken nicht gut zu, weshalb objektrelationale Karten recht komplex sein können. In der Vergangenheit haben Personen Listen/Arrays in MySQL gespeichert, indem sie eine Tabelle erstellt haben, die sie beschreibt, und jeden Wert als eigenen Datensatz hinzugefügt haben. Die Tabelle kann nur 2 oder 3 Spalten enthalten oder viele weitere. Wie Sie diese Art von Daten speichern, hängt wirklich von den Eigenschaften der Daten ab.

Enthält die Liste beispielsweise eine statische oder dynamische Anzahl von Einträgen? Bleibt die Liste klein oder wird sie voraussichtlich auf Millionen von Datensätzen anwachsen? Wird es viele Lesungen auf dieser Tabelle geben? Viele schreibt? Viele Updates? Dies sind alles Faktoren, die bei der Entscheidung über die Speicherung von Datensammlungen berücksichtigt werden müssen.

Auch Key: Value-Datenspeicher/Dokumentenspeicher wie Cassandra, MongoDB, Redis usw. bieten eine gute Lösung. Achten Sie nur darauf, wo die Daten tatsächlich gespeichert werden (wenn sie auf der Festplatte oder im Speicher gespeichert sind). Nicht alle Ihre Daten müssen sich in derselben Datenbank befinden. Einige Daten lassen sich nicht gut einer relationalen Datenbank zuordnen, und es kann sein, dass Sie Gründe dafür haben, sie an einem anderen Ort zu speichern, oder dass Sie eine In-Memory-Key-Value-Datenbank als Hot-Cache für Daten verwenden möchten, die irgendwo auf einer Festplatte oder als kurzlebiger Speicher gespeichert sind für Dinge wie Sitzungen.

43
Charles Addis

Als Nebenbemerkung können Sie Arrays in Postgres speichern.

32
Eric Grotke

Verwenden Sie in MySQL den JSON-Typ.

Im Gegensatz zu den obigen Antworten enthält der SQL-Standard seit fast zwanzig Jahren Array-Typen. Sie sind nützlich, auch wenn MySQL sie nicht implementiert hat.

In Ihrem Beispiel möchten Sie jedoch wahrscheinlich drei Tabellen erstellen: person und fruit und dann person_fruit, um sich ihnen anzuschließen.

DROP TABLE IF EXISTS person_fruit;
DROP TABLE IF EXISTS person;
DROP TABLE IF EXISTS fruit;

CREATE TABLE person (
  person_id   INT           NOT NULL AUTO_INCREMENT,
  person_name VARCHAR(1000) NOT NULL,
  PRIMARY KEY (person_id)
);

CREATE TABLE fruit (
  fruit_id    INT           NOT NULL AUTO_INCREMENT,
  fruit_name  VARCHAR(1000) NOT NULL,
  fruit_color VARCHAR(1000) NOT NULL,
  fruit_price INT           NOT NULL,
  PRIMARY KEY (fruit_id)
);

CREATE TABLE person_fruit (
  pf_id     INT NOT NULL AUTO_INCREMENT,
  pf_person INT NOT NULL,
  pf_fruit  INT NOT NULL,
  PRIMARY KEY (pf_id),
  FOREIGN KEY (pf_person) REFERENCES person (person_id),
  FOREIGN KEY (pf_fruit) REFERENCES fruit (fruit_id)
);

INSERT INTO person (person_name)
VALUES
  ('John'),
  ('Mary'),
  ('John'); -- again

INSERT INTO fruit (fruit_name, fruit_color, fruit_price)
VALUES
  ('Apple', 'red', 1),
  ('orange', 'orange', 2),
  ('pineapple', 'yellow', 3);

INSERT INTO person_fruit (pf_person, pf_fruit)
VALUES
  (1, 1),
  (1, 2),
  (2, 2),
  (2, 3),
  (3, 1),
  (3, 2),
  (3, 3);

Wenn Sie die Person mit einer Reihe von Früchten verknüpfen möchten, können Sie dies mit einer Ansicht tun:

DROP VIEW IF EXISTS person_fruit_summary;
CREATE VIEW person_fruit_summary AS
  SELECT
    person_id                                                                                              AS pfs_person_id,
    max(person_name)                                                                                       AS pfs_person_name,
    cast(concat('[', group_concat(json_quote(fruit_name) ORDER BY fruit_name SEPARATOR ','), ']') as json) AS pfs_fruit_name_array
  FROM
    person
    INNER JOIN person_fruit
      ON person.person_id = person_fruit.pf_person
    INNER JOIN fruit
      ON person_fruit.pf_fruit = fruit.fruit_id
  GROUP BY
    person_id;

Die Ansicht zeigt folgende Daten:

+---------------+-----------------+----------------------------------+
| pfs_person_id | pfs_person_name | pfs_fruit_name_array             |
+---------------+-----------------+----------------------------------+
|             1 | John            | ["Apple", "orange"]              |
|             2 | Mary            | ["orange", "pineapple"]          |
|             3 | John            | ["Apple", "orange", "pineapple"] |
+---------------+-----------------+----------------------------------+

In 5.7.22 möchten Sie JSON_ARRAYAGG verwenden, anstatt das Array zusammen aus einer Zeichenfolge zu hacken.

12
drew

Verwenden Sie den Datenbankfeldtyp BLOB, um Arrays zu speichern.

Ref: http://us.php.net/manual/en/function.serialize.php

Rückgabewerte

Gibt eine Zeichenfolge zurück, die eine Byte-Stream-Darstellung des Werts enthält, der an einer beliebigen Stelle gespeichert werden kann.

Beachten Sie, dass dies eine binäre Zeichenfolge ist, die Null-Bytes enthalten kann und als solche gespeichert und behandelt werden muss. Beispielsweise sollte die serialize () - Ausgabe im Allgemeinen in einem BLOB-Feld in einer Datenbank und nicht in einem CHAR- oder TEXT-Feld gespeichert werden.

2
webdevfreak