Как сохранить список в столбце таблицы базы данных

Итак, за Ответ Mehrdad на соответствующий вопрос, я понимаю, что "правильный" столбец таблицы базы данных не хранит список. Скорее, вы должны создать другую таблицу, которая эффективно удерживает элементы указанного списка, а затем ссылается на него напрямую или через таблицу соединений. Тем не менее, тип списка, который я хочу создать, будет состоять из уникальных элементов (в отличие от связанного примера фруктов вопроса). Кроме того, элементы в моем списке явно отсортированы - это означает, что если бы я сохранил элементы в другой таблице, мне пришлось бы сортировать их каждый раз, когда я обращался к ним. Наконец, список в основном является атомарным в том смысле, что в любое время, когда я захочу получить доступ к списку, мне захочется получить доступ ко всему списку, а не только к его части, поэтому кажется глупым вопрос о том, чтобы выдать запрос базы данных для сбора список.

Решение AKX (связанное выше) представляет собой сериализацию списка и сохранение его в двоичном столбце. Но это также кажется неудобным, потому что это означает, что я должен беспокоиться о сериализации и десериализации.

Есть ли лучшее решение? Если нет лучшего решения, то почему? Кажется, что эта проблема должна возникать время от времени.

... немного больше информации, чтобы вы знали, откуда я. Как только я только начал понимать SQL и базы данных в целом, меня включили LINQ to SQL, и теперь я немного испорчен, потому что я ожидаю иметь дело с моей моделью объектных объектов, не задумываясь о том, как объекты запрашиваются или сохраняются в базе данных.

Спасибо всем!

Джон

UPDATE: Итак, в первой шквал ответов, которые я получаю, я вижу, что "вы можете идти по CSV/XML-маршруту... но НЕ!". Итак, теперь я ищу объяснения, почему. Назовите меня хорошими рекомендациями.

Кроме того, чтобы лучше понять, что я делаю: в моей базе данных есть таблица функций, которая будет иметь список (x, y) пар. (В таблице также будет другая информация, которая не имеет никакого значения для нашего обсуждения.) Мне никогда не понадобится видеть часть списка (x, y) пар. Скорее, я возьму их всех и закрою на экране. Я разрешу пользователю перетаскивать узлы вокруг, чтобы иногда изменять значения или добавлять дополнительные значения в график.

Ответ 1

Нет, нет лучшего способа сохранить последовательность элементов в одном столбце. Реляционные базы данных предназначены специально для хранения одного значения для каждой комбинации строк/столбцов. Чтобы сохранить более одного значения, вы должны сериализовать свой список в одно значение для хранения, а затем десериализовать его при извлечении. Другого способа делать то, о чем вы говорите, нет, потому что то, о чем вы говорите, это плохая идея, которая, как правило, никогда не будет выполнена).

Я понимаю, что вам кажется глупо создавать другую таблицу для хранения этого списка, но это именно то, что делают реляционные базы данных. Вы боретесь с тяжелой битвой и нарушаете один из самых основополагающих принципов реляционной базы данных без уважительной причины. Поскольку вы заявляете, что вы просто изучаете SQL, я бы сильно советовал вам избегать этой идеи и придерживаться рекомендаций, рекомендованных вам более опытными разработчиками SQL.

Принцип, который вы нарушаете, называется первой нормальной формой, которая является первым шагом в нормализации базы данных.

Рискуя упростить ситуацию, нормализация базы данных - это процесс определения вашей базы данных на основе данных, чтобы вы могли писать разумные, последовательные запросы против нее и быть в состоянии поддерживать ее легко. Нормализация предназначена для ограничения логических несоответствий и коррупции в ваших данных, и есть много уровней. Статья Википедии о нормализации базы данных на самом деле довольно хороша.

В принципе, первое правило (или форма) нормализации утверждает, что ваша таблица должна представлять отношение. Это означает, что:

  • Вы должны иметь возможность отличать одну строку от любой другой строки (другими словами, в таблице должно быть что-то, что может служить в качестве первичного ключа. Это также означает, что никакая строка не должна дублироваться.
  • Любое упорядочение данных должно определяться данными, а не физическим упорядочением строк (SQL основан на идее набора, что означает, что единственным упорядочением, на которое вы должны положиться, является то, что вы явно определяете в ваш запрос)
  • Каждое пересечение строк/столбцов должно содержать одно и только одно значение

Последняя точка, очевидно, является главным моментом здесь. SQL предназначен для хранения ваших наборов для вас, а не для предоставления вам "ведра", чтобы вы сами хранили набор. Да, это возможно. Нет, мир не закончится. Тем не менее, вы уже научились понимать SQL и лучшие практики, которые идут вместе с ним, сразу же перейдя на использование ORM. LINQ to SQL - это фантастика, точно так же, как графические калькуляторы. В том же духе, однако, они не должны использоваться в качестве замены для того, чтобы знать, как работают эти процессы.

Теперь ваш список может быть полностью "атомарным", и это может не измениться для этого проекта. Но у вас, однако, будет привычка делать подобные вещи в других проектах, и вы, в конечном счете, (скорее всего, быстро) столкнетесь с сценарием, в котором вы теперь подгоняете свой быстрый n-легкий список в столбце когда это совершенно неуместно. Существует не так много дополнительной работы по созданию правильной таблицы для того, что вы пытаетесь сохранить, и вас не будут высмеивать другие разработчики SQL, когда они увидят ваш дизайн базы данных. Кроме того, LINQ to SQL увидит ваше отношение и автоматически предоставит вам подходящий объектно-ориентированный интерфейс. Почему бы вам отказаться от удобства, предлагаемого вам ORM, чтобы вы могли выполнять нестандартную и нелогичную хакерскую базу данных?

Ответ 2

Вы можете просто забыть SQL все вместе и пойти с подходом "NoSQL". RavenDB, MongoDB и CouchDB, чтобы вспомнить как возможные решения. С помощью подхода NoSQL вы не используете реляционную модель. Вы даже не привязаны к схемам.

Ответ 3

То, что я видел много людей, - это (это может быть не лучший подход, исправьте меня, если я ошибаюсь):

Таблица, которую я использую в примере, приведена ниже (в таблице указаны псевдонимы, которые вы указали своим конкретным подругам. Каждая девушка имеет уникальный идентификатор):

nicknames(id,seq_no,names)

Предположим, вы хотите сохранить много псевдонимов под идентификатором. Вот почему мы включили поле seq_no.

Теперь заполните эти значения в таблице:

(1,1,'sweetheart'), (1,2,'pumpkin'), (2,1,'cutie'), (2,2,'cherry pie')

Если вы хотите найти все имена, которые вы указали своему другу-подруге 1, вы можете использовать:

select names from nicknames where id = 1;

Ответ 4

В дополнение к тому, что говорили все остальные, я бы предложил вам проанализировать ваш подход на более длительные сроки, чем сейчас. В настоящее время элементы уникальны. В настоящее время при использовании элементов потребуется новый список. Почти необходимо, чтобы список в настоящее время невелик. Несмотря на то, что у меня нет специфики домена, не так уж много думать, что эти требования могут измениться. Если вы сериализуете свой список, вы выпекаете в негибкости, которая не нужна в более нормализованном дизайне. Кстати, это не обязательно означает много. Многие отношения. У вас может быть только одна дочерняя таблица с внешним ключом для родителя и столбец символов для элемента.

Если вы все еще хотите перейти по этому пути сериализации списка, вы можете рассмотреть возможность хранения списка в XML. Некоторые базы данных, такие как SQL Server, даже имеют тип данных XML. Единственная причина, по которой я предлагаю XML, состоит в том, что почти по определению этот список должен быть коротким. Если список длинный, то его сериализация в целом - это ужасный подход. Если вы переходите по маршруту CSV, вам нужно учитывать значения, содержащие разделитель, что означает, что вы вынуждены использовать цитируемые идентификаторы. Полагая, что списки коротки, вероятно, не будет иметь большого значения, используете ли вы CSV или XML.

Ответ 5

Если вам нужно запросить список, сохраните его в таблице.

Если вам всегда нужен список, вы можете сохранить его как список с разделителями в столбце. Даже в этом случае, если у вас нет ОЧЕНЬ особых причин, чтобы не хранить его в таблице поиска.

Ответ 6

Я бы просто сохранил его как CSV, если это простые значения, тогда это должно быть все, что вам нужно (XML очень многословный и сериализация в/из него, вероятно, будет излишним, но это тоже будет вариант).

Здесь хороший ответ о том, как вытащить CSV с LINQ.

Ответ 7

Только один вариант не упоминается в ответах. Вы можете де-нормализовать свой дизайн БД. Поэтому вам нужны две таблицы. Одна таблица содержит правильный список, по одному элементу в строке, другая таблица содержит полный список в одном столбце (например, разделенный на комы).

Здесь это "традиционный" дизайн БД:

List(ListID, ListName) 
Item(ItemID,ItemName) 
List_Item(ListID, ItemID, SortOrder)

Здесь это ненормированная таблица:

Lists(ListID, ListContent)

Идея здесь - вы сохраняете таблицу списков с помощью триггеров или кода приложения. Каждый раз, когда вы изменяете содержимое List_Item, соответствующие строки в списках обновляются автоматически. Если вы в основном читаете списки, это может работать неплохо. Плюсы - вы можете читать списки в одном заявлении. Минусы - обновления требуют больше времени и усилий.

Ответ 8

Если вы действительно хотите сохранить его в столбце и запросить много баз данных, поддерживайте XML сейчас. Если вы не запрашиваете, вы можете сохранить их как значения, разделенные запятыми, и проанализировать их с помощью функции, когда вам нужно их разделить. Я согласен со всеми, но если вы хотите использовать реляционную базу данных, большая часть нормализации - это разделение таких данных. Я не говорю, что все данные подходят для реляционной базы данных. Вы всегда можете заглянуть в другие типы баз данных, если многие ваши данные не соответствуют модели.

Ответ 9

Я думаю, что в некоторых случаях вы можете создать "список" FAKE элементов в базе данных, например, в товаре есть несколько фотографий, чтобы показать свои данные, вы можете объединить все идентификаторы изображений, разделенных запятой и хранилищем строка в БД, тогда вам просто нужно проанализировать строку, когда она вам понадобится. Сейчас я работаю над веб-сайтом, и я планирую использовать этот способ.

Ответ 10

Простой ответ: если и только если вы уверены, что список всегда будет использоваться в качестве списка, а затем соедините список вместе на своем конце с символом (например, "\ 0" ), который не будет используется в тексте и хранит это. Затем, когда вы его извлечете, вы можете разделить на "\ 0". Конечно, есть и другие способы решения этой проблемы, но они зависят от конкретного поставщика базы данных.

В качестве примера вы можете сохранить JSON в базе данных Postgres. Если ваш список - это текст, и вам просто нужен список без лишних хлопот, это разумный компромисс.

Другие отважились предложить сериализацию, но я действительно не думаю, что сериализация - хорошая идея. Часть опрятной информации о базах данных заключается в том, что несколько программ, написанных на разных языках, могут разговаривать друг с другом. И программы, сериализованные с использованием формата Java, не будут делать все это хорошо, если программа Lisp захочет загрузить его.

Если вам нужен хороший способ делать такие вещи, обычно доступны массивы или похожие типы. Postgres, например, предлагает массив как тип и позволяет хранить массив текста, если это то, что вы хотите, и есть похожие трюки для MySql и MS SQL с использованием JSON, и IBM DB2 предлагает также тип массива (в их собственной полезной документации). Это не было бы так распространено, если бы не было необходимости в этом.

То, что вы потеряете, перейдя по этой дороге, является понятием списка как последовательность вещей в последовательности. По крайней мере, номинально базы данных обрабатывают поля как единичные значения. Но если это все, что вы хотите, тогда вам следует пойти на это. Это оценочное суждение, которое вы должны сделать для себя.