Итак, согласно ответу Мехрдада на связанный вопрос , я понял, что «правильный» столбец таблицы базы данных не хранит список. Скорее, вы должны создать другую таблицу, которая эффективно содержит элементы указанного списка, а затем связать с ней напрямую или через таблицу соединений. Однако тип списка, который я хочу создать, будет состоять из уникальных элементов (в отличие от плода связанного вопросапример). Кроме того, элементы в моем списке явно отсортированы - это означает, что если бы я сохранил элементы в другой таблице, мне пришлось бы сортировать их каждый раз, когда я к ним обращался. Наконец, список в основном является атомарным в том смысле, что каждый раз, когда я хочу получить доступ к списку, я захочу получить доступ ко всему списку, а не только к его части, поэтому кажется глупым создавать запрос к базе данных, чтобы собрать вместе части список.
Решение AKX (ссылка выше) - сериализовать список и сохранить его в двоичном столбце. Но это также кажется неудобным, потому что это означает, что мне нужно беспокоиться о сериализации и десериализации.
Есть ли лучшее решение? Если нет никакого лучшего решения, то почему? Кажется, что эта проблема должна время от времени возникать.
... еще немного информации, чтобы вы знали, откуда я. Как только я только начал разбираться в SQL и базах данных в целом, меня включили в LINQ to SQL, и теперь я немного избалован, потому что рассчитываю работать со своей объектной моделью программирования, не задумываясь о том, как объекты запрашиваются или хранятся в базе данных.
Спасибо всем!
Джон
ОБНОВЛЕНИЕ: Итак, в первом шквале ответов, которые я получаю, я вижу «вы можете пойти по маршруту CSV / XML ... но НЕ НУЖНО!». Итак, теперь я ищу объяснения, почему. Укажите мне несколько хороших ссылок.
Кроме того, чтобы вы лучше понимали, чем я занимаюсь: в моей базе данных есть таблица функций, в которой будет список пар (x, y). (В таблице также будет другая информация, не имеющая значения для нашего обсуждения.) Мне никогда не понадобится видеть часть списка пар (x, y). Скорее, я возьму их все и нанесу на экран. Я разрешаю пользователю перетаскивать узлы, чтобы время от времени изменять значения или добавлять дополнительные значения к графику.
Вы можете просто забыть о SQL и перейти к подходу «NoSQL». В качестве возможных решений приходят на ум RavenDB , MongoDB и CouchDB . При подходе NoSQL вы не используете реляционную модель ... вы даже не ограничены схемами.
источник
Я видел, что многие люди делают следующее (возможно, это не лучший подход, поправьте меня, если я ошибаюсь):
Таблица, которую я использую в примере, приведена ниже (таблица включает псевдонимы, которые вы дали своим конкретным подругам. У каждой девушки есть уникальный идентификатор):
Предположим, вы хотите сохранить под одним идентификатором много никнеймов. Вот почему мы включили
seq_no
поле.Теперь внесите эти значения в свою таблицу:
Если вы хотите найти все имена, которые вы дали своей подруге с идентификатором 1, вы можете использовать:
источник
Простой ответ: если и только если вы уверены, что список всегда будет использоваться как список, тогда объедините список вместе с вашей стороны с помощью символа (например, '\ 0'), который не будет использоваться в текст когда-либо и сохраните это. Затем, когда вы его получите, вы можете разделить его на '\ 0'. Конечно, есть и другие способы решения этой проблемы, но они зависят от конкретного поставщика базы данных.
Например, вы можете хранить JSON в базе данных Postgres. Если ваш список является текстовым, и вам просто нужен список без лишних хлопот, это разумный компромисс.
Другие рискнули предложить сериализацию, но я не думаю, что сериализация - хорошая идея: часть изящной особенности баз данных состоит в том, что несколько программ, написанных на разных языках, могут взаимодействовать друг с другом. И программы, сериализованные с использованием формата Java, не будут работать так хорошо, если программа на Лиспе захочет их загрузить.
Если вам нужен хороший способ делать такие вещи, обычно доступны массивы или аналогичные типы. Postgres, например, предлагает массив как тип и позволяет хранить массив текста, если это то, что вы хотите , и есть аналогичные приемы для MySql и MS SQL с использованием JSON, а IBM DB2 также предлагает тип массива (в своем собственная полезная документация). Это было бы не так часто, если бы в этом не было необходимости.
Что вы действительно потеряете, идя по этому пути, так это представление о списке как о последовательности элементов. По крайней мере номинально базы данных обрабатывают поля как отдельные значения. Но если это все, что вам нужно, тогда вам стоит пойти на это. Это оценочное суждение, которое вы должны сделать для себя.
источник
В дополнение к тому, что говорили все остальные, я предлагаю вам проанализировать свой подход в более долгосрочной перспективе, чем сейчас. В настоящее время вещи уникальны. В настоящее время для пересортировки элементов потребуется новый список. Практически требуется, чтобы список на данный момент был коротким. Несмотря на то, что у меня нет специфики предметной области, нетрудно предположить, что эти требования могут измениться. Если вы сериализуете свой список, вы теряете гибкость, которая не требуется в более нормализованном дизайне. Кстати, это не обязательно означает полноценные отношения «Многие: многие». У вас может быть только одна дочерняя таблица с внешним ключом для родительского элемента и символьный столбец для элемента.
Если вы все еще хотите пойти по этому пути сериализации списка, вы можете подумать о том, чтобы сохранить список в XML. Некоторые базы данных, такие как SQL Server, даже имеют тип данных XML. Единственная причина, по которой я предлагаю XML, состоит в том, что почти по определению этот список должен быть коротким. Если список длинный, то сериализация его вообще ужасный подход. Если вы идете по маршруту CSV, вам необходимо учитывать значения, содержащие разделитель, что означает, что вы вынуждены использовать цитируемые идентификаторы. Предполагая, что списки короткие, вероятно, не будет большой разницы, используете ли вы CSV или XML.
источник
Я бы просто сохранил его как CSV, если это простые значения, тогда это должно быть все, что вам нужно (XML очень подробный, и его сериализация в / из него, вероятно, была бы излишней, но это тоже был бы вариант).
Вот хороший ответ, как вытащить CSV с помощью LINQ.
источник
Если вам нужно сделать запрос в списке, сохраните его в таблице.
Если вам всегда нужен список, вы можете сохранить его как список с разделителями в столбце. Даже в этом случае, если у вас нет ОЧЕНЬ конкретных причин не делать этого, сохраните его в таблице поиска.
источник
Только один вариант не упоминается в ответах. Вы можете денормализовать дизайн своей БД. Итак, вам нужно две таблицы. Одна таблица содержит правильный список, по одному элементу в строке, другая таблица содержит весь список в одном столбце (например, через запятую).
Вот и «традиционный» дизайн БД:
Вот ненормализованная таблица:
Идея здесь - вы ведете таблицу списков с помощью триггеров или кода приложения. Каждый раз, когда вы изменяете содержимое List_Item, соответствующие строки в списках обновляются автоматически. Если вы в основном читаете списки, это может сработать. Плюсы - можно читать списки в одном утверждении. Минусы - обновления требуют больше времени и усилий.
источник
Если вы действительно хотите сохранить его в столбце и сделать запрос, многие базы данных теперь поддерживают XML. Если вы не запрашиваете, вы можете сохранить их как значения, разделенные запятыми, и проанализировать их с помощью функции, когда они вам понадобятся. Я согласен со всеми остальными, хотя, если вы хотите использовать реляционную базу данных, большая часть нормализации - это разделение таких данных. Я не говорю, что все данные подходят для реляционной базы данных. Вы всегда можете изучить другие типы баз данных, если большая часть ваших данных не соответствует модели.
источник
Я думаю, что в некоторых случаях вы можете создать ЛОЖНЫЙ «список» элементов в базе данных, например, у товара есть несколько изображений, чтобы показать его детали, вы можете объединить все идентификаторы изображений, разделенные запятой, и сохранить строку в БД, тогда вам просто нужно проанализировать строку, когда она вам понадобится. Сейчас я работаю над веб-сайтом и планирую использовать его.
источник
Я очень неохотно выбирал путь, который в конце концов решил пойти, из-за множества ответов. Хотя они добавляют больше понимания в то, что такое SQL и его принципы, я решил стать преступником. Я также не решался публиковать свои выводы, поскольку для некоторых важнее высказать свое разочарование тем, кто нарушает правила, чем понимать, что универсальных истин очень мало.
Я тщательно протестировал его, и в моем конкретном случае он был намного эффективнее, чем использование типа массива (щедро предлагаемого PostgreSQL) или запрос другой таблицы.
Вот мой ответ: я успешно реализовал список в одном поле в PostgreSQL, используя фиксированную длину каждого элемента списка. Допустим, каждый элемент имеет цвет в шестнадцатеричном формате ARGB, это означает 8 символов. Таким образом, вы можете создать свой массив из 10 элементов, умножив его на длину каждого элемента:
Если длина элементов вашего списка различается, вы всегда можете заполнить отступ с помощью \ 0
NB: Очевидно, что это не обязательно лучший подход для шестнадцатеричных чисел, поскольку список целых чисел будет занимать меньше места, но это сделано только для иллюстрации идеи массива с использованием фиксированной длины, выделенной каждому элементу.
Причина: 1 / Очень удобно: получить элемент i по подстроке i * n, (i +1) * n. 2 / Отсутствие накладных расходов на запросы к перекрестным таблицам. 3 / Более эффективный и экономичный на стороне сервера. Список похож на мини-blob, который клиенту придется разделить.
Хотя я уважаю людей, следующих правилам, многие объяснения носят чисто теоретический характер и часто не учитывают, что в некоторых конкретных случаях, особенно при стремлении к оптимальной стоимости с помощью решений с низкой задержкой, некоторые незначительные изменения более чем приветствуются.
«Не дай Бог, что это нарушает какой-то священный священный принцип SQL»: всегда лучше принять более непредубежденный и прагматичный подход перед тем, как декламировать правила. В противном случае вы могли бы закончить как откровенный фанатик, декламирующий Три закона робототехники, прежде чем вас уничтожит Скайнет.
Я не утверждаю, что это решение является прорывом или идеальным с точки зрения удобочитаемости и гибкости базы данных, но оно определенно может дать вам преимущество, когда дело касается задержки.
источник
Многие базы данных SQL позволяют таблице содержать подтаблицу в качестве компонента. Обычный метод - разрешить домену одного из столбцов быть таблицей. Это в дополнение к использованию некоторого соглашения, такого как CSV, для кодирования подструктуры способами, неизвестными СУБД.
Когда Эд Кодд разрабатывал реляционную модель в 1969-1970 годах, он специально определил нормальную форму , которая запрещала бы такое вложение таблиц. Нормальная форма позже была названа Первой нормальной формой. Затем он показал, что для каждой базы данных существует база данных в первой нормальной форме, которая выражает одну и ту же информацию.
Зачем возиться с этим? Ну, базы данных в первой нормальной форме разрешают доступ ко всем данным с ключами. Если вы укажете имя таблицы, значение ключа в этой таблице и имя столбца, база данных будет содержать не более одной ячейки, содержащей один элемент данных.
Если вы разрешите ячейке содержать список, таблицу или любую другую коллекцию, теперь вы не сможете предоставить доступ с ключом к подпунктам без полной переработки идеи ключа.
Ключевой доступ ко всем данным является фундаментальным для реляционной модели. Без этой концепции модель не будет реляционной. Что касается того, почему реляционная модель является хорошей идеей и каковы могут быть ограничения этой хорошей идеи, вы должны взглянуть на 50-летний опыт работы с реляционной моделью.
источник
вы можете сохранить его как текст, который выглядит как список, и создать функцию, которая может возвращать свои данные как фактический список. пример:
база данных:
И функция компилятора списка (написана на python, но должна легко переводиться на большинство других языков программирования). ТЕКСТ представляет текст, загруженный из таблицы sql. возвращает список строк из строки, содержащей список. если вы хотите, чтобы он возвращал целые числа вместо строк, сделайте режим равным 'int'. То же самое с 'string', 'bool' или 'float'.
Также здесь есть функция преобразования списка в строку на случай, если она вам понадобится.
источник