Как хранить массивы в MySQL?
у меня есть две таблицы в MySQL. Таблица человек имеет следующие столбцы:
id | name | fruits
The fruits столбец может содержать null или массив строк, таких как ('apple',' orange',' banana') или ('strawberry') и т. д. Вторая таблица-это таблица фруктов и имеет следующие три столбца:
____________________________
fruit_name | color | price
____________________________
apple | red | 2
____________________________
orange | orange | 3
____________________________
...,...
так как я должен дизайн fruits столбец в первой таблице, так что он может держать массив строк, которые принимают значения из fruit_name столбец во второй таблице? Так как есть нет типа данных массива в MySQL, как я должен это сделать?
7 ответов:
правильный способ сделать это-использовать несколько таблиц и
JOINих в запросах.например:
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`) );The
person_fruitтаблица содержит одну строку для каждого фрукта, с которым связан человек, и эффективно связываетpersonиfruitsтаблицы вместе, т. е.1 | "banana" 1 | "apple" 1 | "orange" 2 | "straberry" 2 | "banana" 2 | "apple"когда вы хотите, чтобы получить человека и все их плоды вы можете сделать что-то вроде этого:
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
причина, по которой в SQL нет массивов, заключается в том, что большинству людей это действительно не нужно. Реляционные базы данных (SQL-это именно то, что) работают с использованием отношений, и в большинстве случаев лучше всего назначить одну строку таблицы каждому "биту информации". Например, где вы можете подумать:" мне нужен список вещей здесь", вместо этого создайте новую таблицу, связав строку в одной таблице со строкой в другой таблице.[1] Таким образом, вы можете представлять отношения M:N. Еще одно преимущество заключается в том, что эти ссылки не будут загромождать строку, содержащую связанный элемент. И база данных может индексировать эти строки. Массивы обычно не индексируются.
Если вам не нужны реляционные базы данных, вы можете использовать, например, хранилище ключей.
читать про нормализация базы данных, пожалуйста. Золотое правило: "[каждый] неключевой [атрибут] должен обеспечивать факт о ключе, весь ключ и ничего, кроме ключа.". Массив делает слишком много. Он имеет несколько фактов, и он хранит порядок (что не связано с самим отношением). И производительность оставляет желать лучшего (см. выше).
представьте, что у вас есть таблица человек и у вас есть таблица с телефонными звонками людей. Теперь вы можете сделать каждый человек строки есть список его телефонных звонков. Но у каждого человека есть много других отношений ко многим другим вещам. Означает ли это, что моя таблица person должна содержать массив для каждой вещи, к которой он подключен? Нет, это не является атрибутом самого человека.
[1]: Это нормально, если связывающая таблица имеет только два столбца (первичные ключи от каждой таблицы)! Если хотя сама связь имеет дополнительные атрибуты, они должны быть представлены в этой таблице в виде столбцов.
MySQL 5.7 теперь предоставляет тип данных JSON. Этот новый тип данных обеспечивает удобный новый способ хранения данных: списки, словари и т. д.
тем не менее, rrays не отображают хорошо базы данных, поэтому объектно-реляционные карты могут быть довольно сложными. Исторически люди хранили списки / массивы в MySQL, создавая таблицу, которая описывает их и добавляет каждое значение как свою собственную запись. Таблица может иметь только 2 или 3 столбца, или она может содержать гораздо больше. Как вы храните этот тип данных зависит от характеристик данных.
например, содержит ли список статическое или динамическое число записей? Будет ли список оставаться небольшим, или ожидается, что он вырастет до миллионов записей? Будет ли много чтения на этом столе? Много пишет? Много обновлений? Это все факторы, которые необходимо учитывать при принятии решения о том, как хранить коллекции данных.
кроме того, ключ: хранилища данных значения / хранилища документов, такие как Cassandra, MongoDB, Рэдис и т. д. обеспечивает хорошее решение, как хорошо. Просто знайте, где на самом деле хранятся данные (если они хранятся на диске или в памяти). Не все ваши данные должны быть в одной базе данных. Некоторые данные плохо сопоставляются с реляционной базой данных, и у вас могут быть причины для ее хранения в другом месте, или вы можете использовать ключ в памяти:база данных значений в качестве горячего кэша для данных, хранящихся на диске где-то или в качестве эфемерного хранилища для таких вещей, как сеансы.
в MySQL используйте тип JSON.
В отличие от ответов выше, стандарт SQL включал типы массивов в течение почти двадцати лет; они полезны, даже если MySQL их не реализовал.
в вашем примере, однако, вы, вероятно, захотите создать три таблицы: person и fruit, а затем person_fruit, чтобы присоединиться к ним.
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);Если вы хотите связать человека с массивом фруктов, вы можете сделать это с видом:
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;посмотреть показывает следующие данные:
+---------------+-----------------+----------------------------------+ | pfs_person_id | pfs_person_name | pfs_fruit_name_array | +---------------+-----------------+----------------------------------+ | 1 | John | ["apple", "orange"] | | 2 | Mary | ["orange", "pineapple"] | | 3 | John | ["apple", "orange", "pineapple"] | +---------------+-----------------+----------------------------------+В 5.7.22, вы хотите использовать JSON_ARRAYAGG, а не взломать массив вместе из строки.
используйте поле базы данных типа BLOB для хранения массивов.
Ref:http://us.php.net/manual/en/function.serialize.php
Возвращаемые Значения
возвращает строку, содержащую байт-потоковое представление значения, которое может храниться в любом месте.
отметим, что это двоичная строка, которая может содержать нулевые байты, и должен храниться и обрабатываться как таковой. Например, сериализовать() выходные данные обычно должны храниться в поле BLOB в базе данных, вместо символа или текстового поля.
вы можете хранить свой массив с помощью group_Concat вот так
INSERT into Table1 (fruits) (SELECT GROUP_CONCAT(fruit_name) from table2) WHERE ..... //your clause hereздесь an пример в скрипку
Comments