Как сохранить список в столбце таблицы базы данных
Итак, за ответ Мехрдада на соответствующий вопрос, я сделать это что" правильный " столбец таблицы базы данных не хранит список. Скорее, вы должны создать другую таблицу, которая эффективно содержит элементы указанного списка, а затем связать с ней напрямую или через таблицу соединений. Однако тип списка, который я хочу создать, будет состоять из уникальных элементов (в отличие от связанного вопроса фруктовое примеру). Кроме того, элементы в моем списке явно разобрались - что это означает, что если я сохраню элементы в другой таблице, мне придется сортировать их каждый раз, когда я обращаюсь к ним. Наконец, список в основном атомарен в том, что каждый раз, когда я хочу получить доступ к списку, я хочу получить доступ ко всему списку, а не только к его части, поэтому кажется глупым выдавать запрос к базе данных, чтобы собрать вместе части списка.
решение AKX (связанное выше) состоит в том, чтобы сериализовать список и сохранить его в двоичном столбце. Но это также кажется неудобным, потому что это означает, что я должен беспокоиться о сериализации и десериализации.
есть ли лучшее решение? Если есть и нет лучшего решения, тогда почему? Кажется, что эта проблема должна возникать время от времени.
... просто немного больше информации, чтобы вы знали, откуда я. Как только я только начал понимать SQL и базы данных в целом, я был включен в LINQ to SQL, и поэтому теперь я немного испорчен, потому что я ожидаю иметь дело с моим Программирование объектной модели без необходимости думать о том, как объекты запрашиваются или хранятся в базе данных.
Спасибо Всем!
Джон
UPDATE: Итак, в первом шквале ответов, которые я получаю, я вижу: "вы можете пойти по маршруту CSV/XML... но не надо!". Так что теперь я ищу объяснения, почему. Укажи мне на несколько хороших ссылок.
кроме того, чтобы дать вам лучшее представление о том, что я: в моей базе данных у меня есть таблица функций, которые будут иметь список пар (x,y). (В таблице также будет содержаться другая информация, которая не имеет никакого значения для нашего обсуждения.) Мне никогда не нужно будет видеть часть списка (x,y) пар. Скорее всего, я возьму все из них и построю их на экране. Я позволю пользователю перетаскивать узлы вокруг, чтобы иногда изменять значения или добавлять больше значений на график.
10 ответов:
нет, нет "лучшего" способа хранить последовательность элементов в одном столбце. Реляционные базы данных разработаны в частности для хранения одного значения на комбинацию строк / столбцов. Чтобы сохранить более одного значения, вы должны сериализовать список в одно значение для хранения, а затем десериализовать его при извлечении. Нет другого способа сделать то, о чем вы говорите (потому что то, о чем вы говорите, это плохая идея, которая вообще никогда не должна быть сделано).
Я понимаю, что вы думаете, что глупо создавать другую таблицу для хранения этого списка, но это именно то, что делают реляционные базы данных. Вы ведете тяжелую битву и нарушаете один из самых основных принципов проектирования реляционных баз данных без уважительной причины. Поскольку вы утверждаете, что вы просто изучаете SQL, я бы сильно советую вам избегать этой идеи и придерживаться практики, рекомендованной вам более опытным SQL разработчики.
принцип, который вы нарушаете, называется первая нормальная форма, что является первым шагом в нормализации баз данных.
рискуя чрезмерно упростить вещи, нормализация базы данных-это процесс определения вашей базы данных на основе того, что данные и, Так что вы можете писать разумные, последовательные запросы против него и быть в состоянии поддерживать его легко. Нормализация предназначена для ограничения логических несоответствий и коррупции в ваши данные, и есть много уровней к нему. Статья в Википедии о нормализация базы данных на самом деле очень хорошо.
в принципе, первое правило (или форма) нормализации утверждает, что ваша таблица должна представлять отношение. Это означает, что:
- вы должны быть в состоянии отличить одну строку от любой другой строки (другими словами, вы таблица должна иметь что-то, что can служить в качестве первичного ключа. Это также означает, что ни одна строка не должна быть дублированным.
- любой порядок данных должен определяться данными, а не физическим порядком строк (SQL основан на идее набора, что означает, что только порядок, на который вы должны полагаться, - это то, что вы явно определяете в своем запросе)
- каждое пересечение строк / столбцов должно содержать один и только один стоимостью
последняя точка, очевидно, является здесь заметной точкой. SQL предназначен для храните свои наборы для вас, а не для того, чтобы предоставить вам "ведро" для хранения набора самостоятельно. Да, это можно сделать. Нет, Конец света не наступит. Однако вы уже искалечили себя в понимании SQL и лучших практик, которые идут вместе с ним, немедленно перейдя к использованию ORM. LINQ to SQL-это фантастика, как и графические калькуляторы. В том же духе, однако, они должны не используется в качестве замены для зная, как процессы, которые они используют на самом деле работа.
теперь ваш список может быть полностью "атомарным", и это может не измениться для этого проекта. Но вы, однако, войдете в привычку делать подобные вещи в других проектах, и вы в конечном итоге (вероятно, быстро) столкнетесь со сценарием, в котором вы теперь приспосабливаете свой быстрый и простой подход к списку в столбце, где он совершенно неуместен. Существует не так много дополнительной работы в создании правильной таблицы для того, что вы пытаетесь сохранить, и вы не будете высмеяны другими разработчиками SQL когда они видят ваш дизайн базы данных. Кроме того, LINQ to SQL увидит ваше отношение и даст вам правильный объектно-ориентированный интерфейс для вашего списка автоматически. Почему бы вам отказаться от удобства, предлагаемого вам ORM, чтобы вы могли выполнять нестандартные и непродуманные хакерские атаки на базы данных?
то, что я видел, многие люди делают это (это может быть не лучший подход, поправьте меня, если я ошибаюсь):
таблица, которую я использую в Примере, приведена ниже (таблица включает в себя прозвища, которые вы дали своим конкретным подругам. Каждая девушка имеет уникальный идентификатор):
nicknames(id,seq_no,names)Предположим, вы хотите хранить много прозвищ в документы. Вот почему мы включили
seq_noполе.теперь заполните эти значения в таблицу:
(1,1,'sweetheart'), (1,2,'pumpkin'), (2,1,'cutie'), (2,2,'cherry pie')если вы хотите найти все имена, которые вы дали своей подруге id 1, то вы можете использовать:
select names from nicknames where id = 1;
в дополнение к тому, что все остальные сказали, я бы предложил вам проанализировать свой подход в более длительных терминах, чем сейчас. Это в настоящее время случай, когда элементы уникальны. Это в настоящее время дело в том, что для обращения к элементам потребуется новый список. Это почти обязательно, что список в настоящее время короче. Несмотря на то, что у меня нет специфики домена, это не так много, чтобы думать, что эти требования могут измениться. Если вы сериализуете свой список, вы выпекаете в негибкости, которая не нужна в более нормализованном дизайне. Кстати, это не обязательно означает полное много:много отношений. Вы можете просто иметь одну дочернюю таблицу с внешним ключом к родительскому элементу и символьным столбцом для элемента.
Если вы все еще хотите пойти по этому пути сериализации списка, вы можете рассмотреть возможность хранения списка в XML. Некоторые базы данных, такие как SQL Server, даже имеют тип данных XML. Единственная причина, по которой я бы предложил XML, заключается в том, что почти по определению, этот список должен быть коротким. Если список длинный, то сериализация его вообще ужасный подход. Если вы идете по маршруту CSV, вам нужно учитывать значения, содержащие разделитель, что означает, что вы вынуждены использовать заключенные в кавычки идентификаторы. Настаивая на том, что списки короткие, вероятно, не будет иметь большого значения, используете ли вы CSV или XML.
Если вам нужно запросить список, то сохраните его в таблице.
Если вы всегда хотите, чтобы список, вы можете сохранить его в виде списка в столбик. Даже в этом случае, если у вас нет очень конкретных причин, чтобы не хранить его в таблице поиска.
Я бы просто сохранил его как CSV, если это простые значения, то это должно быть все, что вам нужно (XML очень подробный и сериализация в/из него, вероятно, будет излишней, но это тоже будет вариант).
здесь хороший ответ для того, как вытащить CSVs с LINQ.
только один вариант не упоминается в ответах. Вы можете де-нормализовать свой дизайн БД. Так что вам нужны две таблицы. Одна таблица содержит правильный список, по одному элементу в строке, другая таблица содержит весь список в одном столбце (например, разделенном комой).
вот это "традиционный" дизайн БД:
List(ListID, ListName) Item(ItemID,ItemName) List_Item(ListID, ItemID, SortOrder)здесь это де-нормализованная таблица:
Lists(ListID, ListContent)идея здесь-вы поддерживаете таблицу списков с помощью триггеров или кода приложения. Каждый раз, когда вы изменяете List_Item содержание, соответствующие строки в списках обновляются автоматически. Если вы в основном читаете списки, это может работать довольно хорошо. Плюсы - вы можете прочитать списки в одном заявлении. Минусы-обновления занимают больше времени и усилий.
Если вы действительно хотели сохранить его в столбце и сделать его доступным для запросов, теперь многие базы данных поддерживают XML. Если вы не запрашиваете, вы можете хранить их как значения, разделенные запятыми, и анализировать их с помощью функции, когда вам нужно их разделить. Я согласен со всеми остальными, хотя, если вы хотите использовать реляционную базу данных, большая часть нормализация-это разделение данных. Я не говорю, что все данные соответствуют реляционной базе данных, хотя. Вы всегда можете заглянуть в другие типы базы данных, если большая часть ваших данных не соответствует модели.
Я думаю, в некоторых случаях, вы можете создать поддельный "список" элементов в базе данных, например, товар имеет несколько фотографий, чтобы показать его детали, вы можете объединить все коды картинки разделены запятой и сохранить строку в БД, то нужно просто разобрать строку, когда вам это нужно. Я работаю на веб-сайте сейчас, и я планирую использовать этот способ.
простой ответ: если и только если вы уверены, что список всегда будет использоваться как список, затем присоедините список вместе с вашим концом с символом (например, "\0"), который никогда не будет использоваться в тексте, и сохраните его. Затем, когда вы его получите, вы можете разделить на '\0'. Конечно, есть и другие способы решения этой проблемы, но они зависят от вашего конкретного поставщика базы данных.
например, вы можете хранить JSON в базе данных Postgres. Если ваш список является текстовым, и вы просто хотите список без дальнейших хлопот, это разумный компромисс.
другие рискнули предложить сериализацию, но я действительно не думаю, что сериализация-хорошая идея: часть аккуратной вещи о базах данных заключается в том, что несколько программ, написанных на разных языках, могут разговаривать друг с другом. И программы, сериализованные с использованием формата Java, не будут делать все это хорошо, если программа Lisp захочет загрузить его.
Если вы хотите хороший способ сделать такие вещи обычно такие или похожие типы. Postgres например, предлагает массив как тип, и позволяет хранить массив текста, если это то, что вы хотите, и есть подобные трюки для MySql и MS SQL используя JSON, и IBM DB2 также предлагают тип массива (в их собственном полезны документации). Это не было бы так часто, если бы не было необходимости в этом.
Что вы теряете, идя, что дорога-это понятие списка как связки вещей в последовательности. По крайней мере номинально, базы данных обрабатывают поля как отдельные значения. Но если это все, что вы хотите, то вы должны пойти на это. Это ценностное суждение, которое вы должны сделать для себя.
Comments