Я пытался спроектировать базу данных в соответствии с концепцией проекта и столкнулся с чем-то горячо обсуждаемым. Я прочитал несколько статей и ответы на некоторые вопросы о переполнении стека, в которых говорится, что хранить (или почти никогда) в поле зрения список идентификаторов и т. П. - все данные должны быть реляционными и т. Д.
Проблема, с которой я сталкиваюсь, заключается в том, что я пытаюсь назначить задачу. Люди будут создавать задачи, назначать их нескольким людям и сохранять в базу данных.
Конечно, если я сохраню эти задачи по отдельности в «Персоне», мне понадобятся десятки фиктивных столбцов «TaskID» и микро-управление ими, поскольку, скажем, одному человеку может быть назначено от 0 до 100 задач.
Опять же, если я сохраню задачи в таблице «Задачи», мне понадобятся десятки фиктивных столбцов «PersonID» и микро-управление ими - та же проблема, что и раньше.
Для такой проблемы можно ли сохранить список идентификаторов, принимающих ту или иную форму, или я просто не думаю о другом способе, которым это можно достичь без нарушения принципов?
источник
VARCHAR ARRAY
) для хранения списка тегов. Вероятно, это не то, как они в конечном итоге будут храниться в дальнейшем, но списки могут быть чрезвычайно полезны на этапах создания прототипов, когда вам не на что больше указывать и вы не хотите создавать всю схему базы данных, прежде чем сможете делай что-нибудь ещеОтветы:
Ключевое слово и ключевое понятие, которое вам нужно исследовать, - это нормализация базы данных .
Вместо добавления информации о назначениях в таблицы лиц или задач вы должны добавить новую таблицу с этой информацией о назначениях и соответствующими взаимосвязями.
Например, у вас есть следующие таблицы:
Количество человек:
Задачи:
Затем вы создадите третью таблицу с заданиями. Эта таблица будет моделировать отношения между людьми и задачами:
Тогда у нас будет ограничение внешнего ключа, так что база данных будет обеспечивать, чтобы PersonId и TaskIds были действительными идентификаторами для этих внешних элементов. Для первой строки, мы можем видеть
PersonId is 1
, поэтому Альфред , присваиваютTaskId 3
, доения коров .То, что вы должны увидеть здесь, это то, что у вас может быть как можно меньше заданий или заданий на одного человека или на одного человека. В этом примере Иезекиилю не назначены никакие задачи, а Альфреду назначено 2. Если у вас есть одно задание с 100 людьми, выполнение
SELECT PersonId from Assignments WHERE TaskId=<whatever>;
приведет к 100 строкам с различными назначенными людьми. Вы можетеWHERE
в PersonId найти все задачи, назначенные этому человеку.Если вы хотите возвращать запросы, заменяя идентификаторы именами и задачами, вы узнаете, как присоединяться к таблицам.
источник
Вы задаете два вопроса здесь.
Сначала вы спрашиваете, нормально ли хранить списки, сериализованные в столбце. Да, это хорошо. Если ваш проект требует этого. Примером могут быть ингредиенты продукта для страницы каталога, где у вас нет желания пытаться отслеживать каждый ингредиент в отдельности.
К сожалению, ваш второй вопрос описывает сценарий, в котором вы должны выбрать более реляционный подход. Вам понадобятся 3 стола. Один для людей, один для задач и один, который поддерживает список задач, назначенных тем или иным людям. Последний будет вертикальным, по одной строке на человека / задачу, со столбцами для вашего первичного ключа, идентификатора задачи и идентификатора человека.
источник
То, что вы описываете, называется отношением «многие ко многим», в вашем случае между
Person
иTask
. Обычно он реализуется с использованием третьей таблицы, иногда называемой таблицей ссылок или перекрестных ссылок. Например:источник
task_id
сначала, если вы делаете запросы, отфильтрованные по задаче.Единственный раз, когда вы можете хранить более одного элемента данных в одном поле, это когда это поле используется только как единое целое и никогда не считается составленным из этих более мелких элементов. Примером может быть изображение, хранящееся в поле BLOB. Он состоит из множества и более мелких элементов (байтов), но они ничего не значат для базы данных и могут использоваться только вместе (и выглядят симпатично для конечного пользователя).
Поскольку «список» по определению состоит из более мелких элементов (элементов), это не тот случай, и вам следует нормализовать данные.
Нет. У вас будет несколько строк в Таблице пересечений (она же Слабая сущность) между человеком и задачей. Базы данных действительно хороши для работы с большим количеством строк; они на самом деле довольно глупы, работая с множеством [повторяющихся] столбцов.
Хороший четкий пример, приведенный по whatsisname.
источник
Это может быть законно в определенных предварительно рассчитанных полях.
Если некоторые из ваших запросов являются дорогостоящими, и вы решили использовать предварительно рассчитанные поля, которые обновляются автоматически с использованием триггеров базы данных, то может быть законно хранить списки внутри столбца.
Например, в пользовательском интерфейсе вы хотите отобразить этот список, используя вид сетки, где каждая строка может открывать полные сведения (с полными списками) после двойного щелчка:
Второй столбец обновляется по триггеру, когда клиент посещает новую статью, или по расписанию.
Вы можете сделать такое поле доступным даже для поиска (как обычный текст).
В таких случаях ведение списков является законным. Вам просто нужно рассмотреть случай возможного превышения максимальной длины поля.
Кроме того, если вы используете Microsoft Access, предлагаемые многозначные поля являются еще одним особым случаем использования. Они обрабатывают ваши списки в поле автоматически.
Но вы всегда можете вернуться к стандартной нормализованной форме, показанной в других ответах.
Резюме: Нормальные формы базы данных являются теоретической моделью, необходимой для понимания важных аспектов моделирования данных. Но, конечно, нормализация не принимает во внимание производительность или другие затраты на получение данных. Это выходит за рамки этой теоретической модели. Но хранение списков или других предварительно рассчитанных (и контролируемых) дубликатов часто требуется при практической реализации.
В свете вышесказанного, в практической реализации, мы бы предпочли запрос, основанный на идеальной нормальной форме и выполняющий 20 секунд, или эквивалентный запрос, основанный на предварительно вычисленных значениях, который занимает 0,08 с? Никому не нравится, когда их программный продукт обвиняют в медлительности.
источник
Даны две таблицы; мы назовем их Person и Task, каждый со своим идентификатором (PersonID, TaskID) ... основная идея - создать третью таблицу, чтобы связать их вместе. Мы назовем эту таблицу PersonToTask. Как минимум, он должен иметь свой собственный идентификатор, а также два других. Так что, когда дело доходит до назначения кого-то для задачи; Вам больше не нужно ОБНОВЛЯТЬ таблицу Person, вам просто нужно ВСТАВИТЬ новую строку в PersonToTaskTable. И обслуживание становится проще - необходимость удаления задачи становится просто УДАЛИТЬ на основе TaskID, больше не нужно обновлять таблицу Person и связанный с ней анализ
Как насчет простого отчета или кто все назначен на задачу?
Вы, конечно, могли бы сделать намного больше; TimeReport может быть сделано, если вы добавили поля DateTime для TaskAssigned и TaskCompleted. Все зависит от тебя
источник
Это может сработать, если, скажем, у вас есть удобные для чтения Первичные ключи и вы хотите получить список задач № без необходимости иметь дело с вертикальной природой структуры таблицы. т.е. намного проще читать первую таблицу.
Тогда возникает вопрос: должен ли список задач храниться или генерироваться по требованию, что во многом будет зависеть от таких требований, как: как часто требуется список, насколько точно существует количество строк данных, как будут использоваться данные и т. Д. ... после чего следует анализировать компромиссы для пользовательского опыта и удовлетворения требований.
Например, сравнение времени, которое потребуется для вызова 2 строк, и выполнения запроса, который сгенерирует 2 строки. Если это занимает много времени, а пользователю не нужен самый актуальный список (* ожидающий менее 1 изменения в день), то он может быть сохранен.
Или, если пользователю нужна историческая запись назначенных ему задач, было бы также целесообразно сохранить список. Так что это действительно зависит от того, что вы делаете, никогда не говори никогда.
источник
Вы берете то, что должно быть другим столом, поворачиваете его на 90 градусов и кладете его в другой стол.
Это похоже на таблицу заказов, в которой есть itemProdcode1, itemQuantity1, itemPrice1 ... itemProdcode37, itemQuantity37, itemPrice37. Помимо того, что вам неудобно обращаться с программным обеспечением, вы можете гарантировать, что завтра кто-то захочет заказать 38 вещей.
Я бы сделал это по-вашему, только если «список» на самом деле не является списком, т. Е. Где он стоит в целом и каждая отдельная позиция не относится к какой-либо четкой и независимой сущности. В этом случае просто запишите все в достаточно большой тип данных.
Таким образом, заказ - это список, а ведомость материалов - это список (или список списков, что было бы еще большим кошмаром для реализации «вбок»). Но примечание / комментарий и стихотворение - нет.
источник
Если это «не нормально», то очень плохо, что каждый сайт Wordpress когда-либо имеет список в wp_usermeta с wp_capabilities в одной строке, список dismissed_wp_pointers в одной строке и другие ...
На самом деле в таких случаях это может быть лучше для скорости, так как вы почти всегда будете хотеть список . Но WordPress не является идеальным примером лучших практик.
источник