Проектирование базы данных: гибкое хранение вопросов и ответов - PullRequest
0 голосов
/ 17 мая 2011

Я давно не проектировал базу данных, и сейчас я не очень уверен в своем дизайне.У меня в основном есть три таблицы в базе данных, которые представляют историю сортов.Я должен изменить эту систему так, чтобы каждый раз, когда добавлялась запись (например, что-то становится историческим), может потребоваться некоторая информация от пользователя.Иногда у них будет только один простой вопрос, в других случаях они должны будут предоставить пять различных частей информации, и конечный пользователь должен гибко управлять им через административный интерфейс.Поэтому я планирую иметь таблицу вопросов и таблицу ответов с составными таблицами, чтобы связать их с тремя другими таблицами.Я борюсь с дизайном таблицы ответов, потому что на каждый вопрос могут потребоваться различные ответы.Некоторые ответы будут выпадающими выборами, которые связаны с другой базой данных через внешний ключ.Другими могут быть ввод текста, даты или ответы Да / Нет.Прямо сейчас у меня есть таблица ответов, которая охватывает все типы ответов с серией пустых полей ...

+----------------------------+
| Answer                     |
+----------------------------+
| Id (int)                   |
| QuestionId (int)           |
| ForeignKeyId1* (int)       |
| ForeignKeyId2* (int)       |
| ForeignKeyId3* (int)       |
| Number* (bigint)           |
| DateField* (date)          |
| Text* (varchar 500)        |
| YesNo* (bit)               |
+----------------------------+
  *Nullable

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

Это плохой дизайн?Что может сделать его лучше?

Ответы [ 2 ]

1 голос
/ 22 мая 2011

Можно использовать разные поля для разных типов данных, как и несколько внешних ключей.Такая конструкция обеспечивает максимально возможную целостность предметной области в СУБД.Это философски хороший путь, так как большинство людей скажет вам, что если DMBS сделает всю работу за вас, вы сэкономите на написании и поддержке кода.Я бы был одним из таких людей большую часть времени.

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

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

ANSWER
( Id (int)
, QuestionId (int)
, Part (int)
, Value (nvarchar 1000)
)

Если я правильно понял ваш вопрос, вопрос может иметь многочастичный ответ.Предполагая, что на один вопрос потенциально может быть несколько ответов, и что ваши контрольные таблицы знают, какая часть является какой, вы должны использовать поле Часть для различения частей.Если на каждый вопрос задано ровно ноль или один ответ, вам не нужна таблица ответов, вы можете просто добавить ответ на вопрос.

Итак, почему вы можете отказаться от того, чтобы база данных применялась принудительно?целостность предметной области?Вот относительные плюсы и минусы:

Преимущества нескольких отдельных полей ответа:

  • СУБД не позволит вам ввести неправильный вид данных вполе, поэтому вам не нужно писать или вызывать какие-либо функции целостности предметной области перед сохранением данных (если только вы не хотите перехватывать эти ошибки на уровне графического интерфейса пользователя)
  • Нет путаницы в том, как интерпретировать содержимоеответ (например, какой месяц и какой день в этой дате ответа ...)

Преимущества поля ответа Catch All:

  • Вам не нужно писать дополнительный код для просмотра типа вопроса, чтобы выяснить, какой столбец в таблице ОТВЕТОВ нужно прочитать для данного вопроса любого типа.
  • Вам не нужно менять свой вопрос.схема базы данных / физическое заполнение базы данных каждый раз, когда добавляется новая справочная таблица или тип данных ответа.

В любом случае вам необходимо написать некоторый код для обработки того факта, что вы храните семантически разныеОтвечает на несколько вопросов в одном хранилище данных.Вы должны решить, какой тип дополнительного кода вы хотите написать, тип, который определяет, куда поместить и найти ответ каждого типа, или тип, который определяет, как хранить и интерпретировать различные типы данных, используя общее представление (то есть строку).

Учитывая, что изменение таблицы, в которой есть данные, - это боль, и учитывая, что большинство языков программирования имеют довольно надежную встроенную функциональность типа .ToString () / .TryParse (), я бы склонялся к использованиюуниверсальный подход, если моей главной заботой была ремонтопригодность.

1 голос
/ 17 мая 2011

Из того, что вы описали, ваше решение выглядит так, как будто оно должно работать нормально. Я сделал аналогичные настройки с таблицами, столбцы которых настроены для записи определенных типов данных, что позволяет другим полям обнуляться. Выглядит хорошо для меня, хотя я не уверен, для чего нужны ваши поля ForeignKeyID: \

...