Отличный вопрос, и то, что вы задаете его перед созданием приложения, говорит о многом для вашей способности учиться и совершенствовать свои навыки моделирования данных.
Ограничения вашей модели
Это нормализовано в простом смысле: вы уже решили, что такое сущности; какие отношения вам нужны; вы даже решили, что это бессмысленные вещи, не имеющие идентифицирующих характеристик, и вы дали им столбцы IDENTITY в качестве физических ключей. Тогда вы нормализовали таблицы.
Это не имеет ничего общего с реляционной моделью или нормализацией.
Это типичное мышление с точки зрения приложения (понятно, потому что это все, что у вас есть, и вы знаете функциональные потребности). Но это не имеет ничего общего с данными. если вы создадите его с этой точки зрения, вы не получите базу данных, вы получите место для хранения приложения. Теперь, если приложение должно было быть написано для одного теста и выброшено, это было бы приемлемо. Но если тест будет проводиться в течение месяца или двух; если компания все еще будет существовать через десять лет; если тесты будут расти; если статистика, которая будет запущена, будет расти, улучшаться и развиваться ... ну, у вас будет немало проблем. Каждый раз, когда вы улучшаете приложение, вам придется заменять его «базу данных». В какой-то момент они решат, что приложение (и содержащаяся в нем «база данных») слишком дороги для изменения, и откажутся от них обоих.
Даже на короткое время существования приложения, поскольку сбор данных не нормализован, он очень ограничен, «мощность» РМ, то, что реализовано в каждой коммерческой СУБД, теряется для вас. Навигация (которая в любом случае громоздка из-за громоздкости SQL-соединений) еще более громоздка. Например. чтобы перейти от ребенка к бабушке и дедушке, вы вынуждены получить родителя, даже если не получаете никаких столбцов из него. Пользователь может получить доступ только к данным через приложение, оно «закрыто». В настоящее время существуют тысячи инструментов отчетов, которые подключаются к базе данных и позволяют пользователям выполнять все виды запросов, которые еще не были идентифицированы, без необходимости ждать запроса на изменение, который будет реализован командой приложения: способность потеряна. И вам придется «пересчитывать» кучу данных каждый год или около того.
Nomalisation
Нормализация создает открытые базы данных, которые разрешают такой доступ без ограничений.
Данные живут намного дольше, чем приложение. Он выживает в приложении и имеет ценность для организации. Когда приложение заменяется, они извлекают данные и хотят, чтобы приложение замены было готово с загруженными данными. Если они не использовали модельера данных, новый дизайнер приложений не извлек бы уроков из ошибок старых разработчиков приложений, и все повторяется.
Хорошо, значит, организация планирует существовать в следующем году. Итак, вы собираетесь запустить более одной викторины в производстве. Итак, вы наняли модельера данных, чтобы он следил за вашей коллекцией данных, чтобы вы не допустили этих ошибок. Отлично. Спасибо. Я принимаю.
Реляционное моделирование 203
Данные смоделированы (а) полностью независимо от приложения и любых функций, о которых вы можете знать, и (б) с использованием совершенно разных методов, о которых разработчики приложений не знают.Итак, начнем.Это не формальный урок нормализации (это займет слишком много времени, и теория утомит вас до смерти);это просто смотрит через плечо моделиста, пока он работает.Все, что вам нужно сделать, это ответить на вопросы [каждый раз, когда я размещаю знак вопроса, пожалуйста, остановитесь и ответьте, прежде чем двигаться дальше], честно (не предполагая, что вы нечестны; просто подтверждение того, что «я не знаю», вполне приемлемо, потому чтоон определяет область, над которой мы должны работать, тогда как четкие утвердительные и отрицательные позволяют нам избежать обсуждения).Кроме того, прости меня, но я приму ответы, чтобы избежать задержек в обратном направлении;пожалуйста, укажите на любую из моих ошибок, и я исправлю модель.
Хорошо, у вас есть некоторые сущности, с которыми вы в курсе, так что давайте начнем с них, я думаю, что они выглядят так Каракули в песке .Я намеренно не использую стандартные символы, потому что я не хочу, чтобы эти значения были включены в него на данном этапе, потому что мы не достигли этих значений, и мы не хотим передавать ложные ожидания людям (включая нас), которые понимают стандартные символы.
Как строки в каждой сущности идентифицируются уникальным образом из каждой другой строки?(Это важно, потому что это помогает нам проверить, что сущность на самом деле является сущностью, а не Дональдом Даком, что-то ненастоящее.) Из представленных столбцов вы могли бы (по крайней мере):
Question.Question
.
СМИ?Как именно, я собираюсь убедиться, что нет 42 идентичных изображений?Если я позволю это, вы ударят по моему заднему концу, когда наш босс закричит на вас, а затем он также ударит по нему.ИДЕНТИЧНОСТЬ не поможет мне, она с радостью позволит мне вставлять дубликаты.FileName - это хороший идентификатор.Media.FileName
.
Тема?Вы хотели бы 101 идентичные темы?Я думал, что нет.
Тема. Тема.
. * 1054. * Тема.№ ИДЕНТИЧНОСТЬ?Нет. Вы совершенно ясно, что это относится к теме, и я уже несу тему как иностранный ключ, который имеет значение;если это зависимый ребенок, а не независимый сирота, то FK является Идентификационным отношением :
Подтема: (Тема, подтема).
.
Хорошо, у нас есть фюзеляж.
Как сущности связаны друг с другом?
Вам ясно, что подтема является дочерним элементом темы, отлично.
.
Вопрос является дочерним элементом подтемы?Думаю, нет.Вы действительно хотите задать тот же вопрос «Сколько автомобилей принадлежит семье», который может существовать в 42 викторинах, вставленных в 42 ряда?«никогда не будет одного и того же вопроса в двух викторинах» подозрительно, поэтому, пожалуйста, не говорите этого, если вы не собираетесь поставить его в письменном виде.Что еще хуже, скажем, вопрос очень колоритный, тогда у нас будет также 42 медиа-материала.Если босс расстраивается из-за необходимости изменить один и тот же вопрос в 42 местах, и когда он делает это, он находит, что некоторые изображения были древними, они не обновлялись, когда основное обновление изображений имело место в прошлом году ... это ваш задний план.
.
Как насчет того, чтобы допустить возможность Вопроса, существующего более чем в одном Тесте?
.
То есть Вопрос не зависит.
Вернуться к сущностям. В наших обсуждениях, начиная с пятого слова, вы продолжаете говорить «Викторина», а я продолжаю говорить это, но у нас нет сущности для этого. Я не могу представить свободный и дублированный набор Вопросов, который я только что дедуплицировал, без идентификации упомянутой коллекции Вопросов. Теперь вы можете сказать «на самом деле Викторина - это тема», но это очень ограничительно: каждый раз, когда босс должен добавить тест для какого-то нового клиента, он должен добавить всю тему / подтему / вопрос набор снова и снова, даже когда он знает, что уже вводил эти точные вопросы в существующие викторины; вот почему он выиграл новый бизнес, и почему он собирался наконец получить прибыль, которую вы только что сократили до нуля. Мой задний конец все еще болит от его последнего расстройства, поэтому давайте удостоверимся, что у него нет другого оправдания. Это позволит ему расти, развивать и изменять викторины и темы / подтемы независимо друг от друга, без дублирования Вопросов:
.
Сущность. Викторина
Ключ? Что ж, лучше иметь индекс, чтобы мы не поставили ему дубликаты Викторины. Допустим, мы не хотим нести ключи CHAR (80) в дочерние элементы, и пользователь считает, что короткое имя CHAR (12), которое они составляют, является хорошим идентификатором, а не десятизначным числом.
Викторина: QuizCode
,
хорошо, у нас достаточно большой фюзеляж для полезной нагрузки. Пока что у нас есть Улучшенный каракули на песке .
Какие сущности действительно независимы, которые могут существовать без существования других сущностей; и остаток, который существует только в контексте другой сущности?
СМИ все еще немного в воздухе. Хотя мы исключили повторяющиеся имена файлов, мы не разрешали использовать одно и то же изображение в более чем одном вопросе. Давайте позволим это. Мы не хотим ИДЕНТИЧНОСТИ, мы уже несем вопрос PK, поэтому он (а) является зависимым и (б) идентифицирован родителем.
.
Вопрос PK как CHAR (255) был хорош прежде, но носить его как FK у ребенка становится глупо. Вам нравится IDENTITY, и будут миллионы Вопросов. Хорошо.
Question.QuestionId
.
Давайте дадим этим Независимым Сущностям квадратные углы и оставим детям Зависимых Сущностей . Теперь у нас есть почти, но не совсем, диаграмма отношений сущностей .
Давайте закончим отношения. Пока что имеем:
У Викторины может быть много Вопросов, и Вопрос может существовать во многих Викторинах.
Вопрос - дитя подтемы, но он независим.
Медиа существует только в контексте Вопроса, как вариант.
.
Поскольку мы живем во Вселенной, в которой есть какой-то порядок, и наше стремление является научным, давайте дадим ребенку такой порядок. Я думаю, что теперь мы имеем право на Диаграмма логических отношений сущностей .
Сплошные линии: Идентифицирующие отношения ; ломаные линии нет. Теперь, поскольку мы применили некоторые стандартные требования к сущностям и отношениям, мы можем использовать стандартные символы. Не стесняйтесь указывать на мои ошибки.
Вот и все, мы закончили. Надеюсь, я передал, что это упражнение туда-сюда, поэтому оно называется моделированием. У астронавтов есть отдельные частные помещения, и они могут общаться друг с другом.
-------------------------------------------- ----------------------------------------------
Что это? Вам нужна Модель данных ? Хорошо, дай мне пять минут. Пожалуйста, возьмите кофе для себя.
-------------------------------------------- ----------------------------------------------
Он достаточно мал, чтобы я мог дать вам физическую Модель данных . Я использую методологию IDEF1X для моделирования реляционных баз данных, которая является стандартной, поэтому модель данных отображается в нотации IDEF1X , пожалуйста проверьте эту ссылку, если вам нужен быстрый обзор того, что означают символы.
,
Отношения «многие ко многим» представляют собой логическую концепцию, и они нарисованы в логической модели. Они реализованы в виде ассоциативных таблиц в физической модели. Я поставил это. Нормализованная база данных имеет больше таблиц (нечего бояться), но меньше столбцов на таблицу, и нет повторяющихся столбцов (без аномалий обновления).
Боже мой. Колонки «Тема» и «Подзаголовок» огромны! Мы не можем перенести эти жирные внешние ключи в Вопрос. [Обсудите с бизнес-пользователями.] Хорошо, они говорят, что будет только сто Тем и несколько тысяч подтем. Нет нумерации (10,0). Они хотят, чтобы в раскрывающихся списках была полная тема и подтема, и они согласны, что она должна быть уникальной, но дополнительный короткий код CHAR (6) был бы хорош.
Видите, оно идет взад-вперед. Бумага дешевая; обсудить с кем угодно и всеми; улучшать, исправлять, изменять, модулировать, улучшать без создания единой таблицы или написания строки кода; у вас будет модель для написания кода. Все остальное не . Единственный способ учиться - это представить что-то твердое, а потом отбросить или изменить; делайте все свои ошибки на бумаге, а не в базе данных.
Обратите внимание, что суррогатная клавиша всегда дополнительная клавиша, дополнительный индекс. Они никогда заменяют Ключ (то, что у вас было, и о чем Эдди пытался заставить вас задуматься: вы не предотвращали дубликаты, вы просто имели бессмысленный ключ, гарантирующий уникальность строк как электронная таблица и ложное чувство безопасности). Поэтому нам нужно свести их к минимуму, а не ставить их волей-неволей на каждом столе.
Надеюсь, я показал выше, что упрощенные правила, такие как "никогда не используйте суррогаты" и "всегда используйте суррогаты", слишком глупы для обсуждения. Нет, тщательное моделирование означает: поймите и примите во внимание, что они являются дополнительными , а не заменяют настоящий Ключ. Используйте только тогда, когда вам нужно, и когда вы должны их использовать. Здесь мне удалось сойти с рук только с одной личностью. И три коротких кода, которые имеют значение для пользователей, являются суррогатами, но они имеют значение; Столбцы IDENTITY не имеют (они в конечном итоге имеют значение, которое они не могут поддерживать, что является частью проблемы).
Я оставлю вам DataTypes. Но имейте в виду, столбцы varchars и Nullable заставляют столбец быть переменным. Действительно медленный, если используется в индексе (каждая запись должна иметь небольшую «распаковку» при каждом доступе, даже на промежуточных уровнях), поэтому этого следует избегать, если только вы не хотите предоставить боссу медленную базу данных.
Точно так же, если вы не хотите, чтобы накладные расходы ваших строк на странице перемещались при каждом обновлении, столбцы фиксированной длины все вокруг. А это значит, что мы не можем быть ленивыми и всеобщим.
Хорошо, теперь у нас есть камера для ракетного топлива.
Ответ на комментарии 1
из вашей последней модели данных, было бы лучше, если бы я опустил topicCode из таблицы вопросов? Не кажется ли вам излишним включать topicCode как в подтемы, так и в таблицы вопросов?
Отличный вопрос.
(Последний, пятый, это Модель данных; четвертый - это Диаграмма Отношений Сущностей; первые три - это круговая диаграмма в небе.)
Первичный ключ, перенесенный в дочерний ключ как внешний ключ, не является избыточным, он необходим.
Subtopic PK - это (TopicCode, SubtopicCode) составной ключ (который поддерживаются коммерческими базами данных, как требование реляционной модели). Выше горизонтальной линии в подтеме.
- Некоторые разработчики боятся составных ключей, потому что им требуется более одной ссылки в предложении WHERE (чистая лень; SQL громоздок с объединениями; справляется с этим).
,
Это потому, что отношение Topic :: Subtopic является Идентифицирующим отношением , что означает, что PK Родителя используется для создания PK Дочернего, образуя Составной Ключ. Обратите внимание, что родительский PK в любом случае должен переноситься в Child, как FK, поэтому он не является избыточным; требуется. Известно, что это существенно увеличивает «мощность» или «реляционность» БД и существенно повышает удобство использования (опытные пользователи часто более опытны в использовании RDb, чем разработчики).
- Вот почему он определяется как стандарт: IDEF1X - это стандарт, который обеспечивает более строгое применение реляционной модели; он способствует вдумчивому рассмотрению всех ключей, что, конечно, имеет решающее значение для «реляционности» предполагаемой реляционной базы данных.
,
В вопросе FK для подтемы, следовательно, (TopicCode, SubtopicCode).
Если вы использовали идентификаторы в теме и подтопе, тогда вопрос имел бы (SubtopicId) в качестве FK для подтемы, и вы теряете как навигационные возможности, так и значение.
- Одной из причин того, что использование составных ключей, которые идентифицируют родителя (и прародителя), лучше, чем использование идентификаторов, является, например когда вам нужны только столбцы из Вопроса и Темы, у нет , чтобы ВЫБРАТЬ из подтемы, вы можете получить TopicCode непосредственно из Вопроса; в то время как с идентификаторами вы вынуждены ВЫБРАТЬ из подузла, что не является частью требования к отчету, это навязывание из-за плохого реляционного моделирования; Неспособность реализовать идентификационные отношения, сильный смысл. Просто одна из причин, по которой кучи данных, имеющие идентификаторы только в виде PK (переносимые как FK), выполняют гораздо больше работы, чем нормализованные реляционные базы данных.
- Поскольку соответствующие таблицы просты и малы, это может не быть хорошим примером для демонстрации превосходства реляционных ключей / ограничения столбцов IDENTITY; рассмотрим любые большие таблицы Grandparent :: Parent :: Child.
- Лучшим примером для демонстрации этого превосходства / ограничения, которое заслуживает рассмотрения для всех, кто хочет продолжить обсуждение этого вопроса, является модель данных из моего расширенного курса , поскольку адресовано явно.
- Другая причина - потерянный смысл. Например. пользователь может просто ВЫБЕРИТЬ TopicCode, SubtopicCode, Question FROM Question и разобраться в наборе результатов.
Ответ на комментарии 2
Модель прогрессивных данных 101102
Ответ на комментарии 3
Я не понимаю, как вы можете использовать один и тот же файл изображения с разными вопросами?
Простой, например. «назвать нелетающую птицу» и «что такое эму» могут использовать одну и ту же фотографию эму. Это было мое предположение согласно (1) в основном посте выше. Модель позволяет это сделать, предоставив неуникальный индекс для FileName.
Следует ли включить внешний ключ Media.FileName в таблицу вопросов и удалить QuestionId из таблицы носителей?
Ну нет. В том, как я его смоделировал, есть несколько преимуществ. Если он находится в таблице вопросов, то какое-то большое зелье времени будет нулевым. Вам нужен индекс по имени файла для поиска по ним; посмотрите, используется ли он; или нет; и т.д. Это означает, что мы не можем индексировать столбец FileName (или мы можем индексировать его, но индекс будет медленным из-за пустых значений). Прямо сейчас это моделируется как:
- «вариант» или подтип вопроса (тот, у которого есть изображение)
- Нет нуля
- Быстрый неуникальный индекс
Может быть настроен как банк изображений (уникальный индекс).Мы знаем, что у Вопроса могут быть ноль к одному Изображения.Вы можете сообщить нам свои решения, и я поменяю модель:
- Изображения являются уникальными для FileName;они могут использоваться только в одном вопросе
- Изображения являются уникальными для FileName;они могут использоваться более чем в одном вопросе
И что это за отношения?1 :: 1?
Да.С Медиа конец "оптональный".Точно: один вопрос имеет ноль или один носитель.Следовательно, «Может иметь» - это глагольная фраза или заголовок отношения.
Модель построена с учетом естественной иерархии: родители выше детей;подтипы находятся на одной горизонтали.
Не похоже на другие отношения n :: n или 1 :: n.
Нет отношений n :: n,(Был один на логическом уровне; он был реализован как ассоциативная таблица на физическом уровне.)
** Почему вы включили поле «Ответ» в таблицу QuizQuestion? *
Гдехотите ли вы хранить ответы пользователей?
Видите, вам нужны таблицы Quiz и QuizQuestion;раньше они были действительными объектами, тогда вы этого не видели, но теперь видите.
Взаимосвязь между темами и подтемами определена в таблице подтем.В таблице вопросов вы включили TopicCode и SubtopicCode.Вы сказали (если я не ошибаюсь), что включение TopicCode - это хорошо, потому что я могу попасть в тему непосредственно из таблицы вопросов, не присоединяясь к таблице подтем.
Да.Согласно (1.Subtopic) выше.
Но, учитывая вашу модель, каждый раз, когда я вношу новый вопрос в БД, я должен выбрать тему и подтему [для вопроса, изсуществующий список].
Ну, вы все равно должны это сделать;модель только усиливает это.Я понял (из данных), что это то, что вам нужно.Один Suptopic может принадлежать более чем одной теме.Таким образом, вы должны задать ей и тему, и подтему (конкретную комбинацию).
Как эта база данных гарантирует, что подтема относится к определенной теме, как описано в таблице подтем?
Вы этого не видите?Можете ли вы увидеть, что таблица подтем уже содержит определенные [все, что вы вставили] Тема :: комбинации подтем ... а не другие?Хорошо, поэтому, когда вы добавляете новый Вопрос и задаете ему Тему и подтему (которая является Первичным ключом Подтопы и рассматриваемым Внешним ключом), база данных принудительно применяет FK, так что только одна из комбинаций Темы:: Можно использовать подтемы, которые существуют в SubTopic.
Это небольшое представление о силе хороших естественных реляционных ключей.
В этом прелесть хорошей реляционной модели: она предъявляет множество требований отодна [правильно смоделированная] структура.
Ответ на комментарии 4
Модель данных с прогрессивными данными 101103
Прогрессивные данные Модель 101109
Обозначение IDEF1X