web-dev-qa-db-fra.com

Comment stocker des tableaux dans MySQL?

J'ai deux tables dans MySQL. Table Person a les colonnes suivantes:

id | name | fruits

La colonne fruits peut contenir null ou un tableau de chaînes telles que ('Pomme', 'Orange', 'Banane') ou ('Fraise'), etc. Le second tableau est Table Fruit et contient les trois suivants Colonnes:

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

Alors, comment devrais-je concevoir la colonne fruits dans la première table afin qu'elle puisse contenir un tableau de chaînes prenant des valeurs de la colonne fruit_name dans la deuxième table? Puisqu'il n'y a pas de type de données tableau dans MySQL, comment dois-je le faire?

89
tonga

Pour ce faire, utilisez plusieurs tables et JOIN dans vos requêtes.

Par exemple:

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

La table person_fruit contient une ligne pour chaque fruit auquel une personne est associée et relie efficacement les tables person et fruits, I.E.

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

Lorsque vous voulez récupérer une personne et tous ses fruits, vous pouvez faire quelque chose comme ceci:

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

La raison pour laquelle il n'y a pas de tableaux en SQL, c'est parce que la plupart des gens n'en ont pas vraiment besoin. Les bases de données relationnelles (SQL c'est exactement ça) fonctionnent à l'aide de relations, et la plupart du temps, il est préférable d'assigner une ligne d'une table à chaque "bit d'information". Par exemple, là où vous pouvez penser "J'aimerais avoir une liste de choses ici", créez plutôt une nouvelle table en reliant la ligne d'une table à la ligne d'une autre table. [1] De cette façon, vous pouvez représenter les relations M: N. Un autre avantage est que ces liens n'encombreront pas la ligne contenant l'élément lié. Et la base de données peut indexer ces lignes. Les tableaux ne sont généralement pas indexés.

Si vous n'avez pas besoin de bases de données relationnelles, vous pouvez utiliser par exemple un magasin clé-valeur.

Lisez à propos de normalisation de la base de données , s'il vous plaît. La règle d'or est la suivante: "[Chaque attribut] non clé doit fournir un fait concernant la clé, la clé entière et rien que la clé.". Un tableau en fait trop. Il a plusieurs faits et stocke la commande (qui n'est pas liée à la relation elle-même). Et la performance est médiocre (voir ci-dessus).

Imaginez que vous ayez une table de personne et que vous ayez une table avec des appels téléphoniques de personnes. Maintenant, vous pouvez faire en sorte que chaque personne ait une liste de ses appels téléphoniques. Mais chaque personne a beaucoup d'autres relations avec beaucoup d'autres choses. Est-ce que cela signifie que ma table de personnes devrait contenir un tableau pour chaque chose à laquelle il est connecté? Non, ce n'est pas un attribut de la personne elle-même.

[1]: Ce n'est pas grave si la table de liaison ne comporte que deux colonnes (les clés primaires de chaque table)! Si la relation elle-même comporte des attributs supplémentaires, ils doivent être représentés dans cette table sous forme de colonnes.

50
Janus Troelsen

MySQL 5.7 fournit maintenant un type de données JSON . Ce nouveau type de données offre un nouveau moyen pratique de stocker des données complexes: listes, dictionnaires, etc.

Cela dit, les rrays ne mappent pas correctement les bases de données, ce qui explique pourquoi les mappages objet-relationnels peuvent être assez complexes. Historiquement, les gens stockaient des listes/des tableaux dans MySQL en créant une table qui les décrivait et en ajoutant chaque valeur en tant que son propre enregistrement. La table peut ne comporter que 2 ou 3 colonnes, ou bien en contenir beaucoup plus. La façon dont vous stockez ce type de données dépend vraiment de leurs caractéristiques.

Par exemple, la liste contient-elle un nombre d'entrées statique ou dynamique? La liste restera-t-elle petite ou doit-on compter des millions de disques? Y aura-t-il beaucoup de lectures sur cette table? Beaucoup d'écrit? Beaucoup de mises à jour? Tous ces facteurs doivent être pris en compte lors du choix du stockage des collections de données.

En outre, les clés: magasins de données de valeur/magasins de documents tels que Cassandra, MongoDB, Redis, etc. constituent également une bonne solution. Sachez simplement où les données sont réellement stockées (si elles sont stockées sur disque ou en mémoire). Toutes vos données ne doivent pas nécessairement se trouver dans la même base de données. Certaines données ne correspondent pas bien à une base de données relationnelle et vous pouvez avoir des raisons de les stocker ailleurs ou vous pouvez utiliser une base de données key-in memory: value en tant que cache dynamique pour les données stockées sur un disque ou en tant que stockage éphémère. pour des choses comme des sessions.

43
Charles Addis

Une remarque à prendre en compte, vous pouvez stocker des tableaux dans Postgres.

32
Eric Grotke

Dans MySQL, utilisez le type JSON.

Contrairement aux réponses ci-dessus, le standard SQL inclut les types de tableaux depuis près de vingt ans; ils sont utiles, même si MySQL ne les a pas implémentés.

Dans votre exemple, cependant, vous souhaiterez probablement créer trois tables: personne et fruit, puis personne_fruit pour les rejoindre.

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

Si vous souhaitez associer la personne à un tableau de fruits, vous pouvez le faire avec une vue:

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;

La vue affiche les données suivantes:

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

Dans la version 5.7.22, vous souhaiterez utiliser JSON_ARRAYAGG , plutôt que de pirater le tableau à partir d'une chaîne.

12
drew

Utilisez le type de champ BLOB de la base de données pour stocker les tableaux.

Réf.: http://us.php.net/manual/en/function.serialize.php

Valeurs de retour

Renvoie une chaîne contenant une représentation sous forme de flux d'octets pouvant être stockée n'importe où.

Notez qu'il s'agit d'une chaîne binaire pouvant inclure des octets nuls. Elle doit être stockée et traitée comme telle. Par exemple, la sortie serialize () doit généralement être stockée dans un champ BLOB d'une base de données, plutôt que dans un champ CHAR ou TEXT.

2
webdevfreak