Советы по базовому дизайну, первый раз дизайн базы данных

8

Я беру курс, чтобы стать разработчиком Java.

Курс предполагает использование баз данных, но, к сожалению, мы никогда не проектируем их.

Большую часть времени мы получаем готовые базы данных, и нам приходится внедрять в них код для вставки, обновления, чтения или удаления данных.

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

Я надеюсь, что эти типы вопросов разрешены здесь и что они не будут слишком широкими.


Это небольшой дизайн, который я сделал для чего-то простого, как clubsи membersс addressesи phonenumbers.

  • Там будет несколько клубов.
  • Каждый клуб будет иметь несколько членов (очевидно)
  • Член не может быть частью нескольких клубов
  • Участник может иметь несколько телефонных номеров и адресов электронной почты.
  • Член может иметь только один адрес
  • Адрес может принадлежать разным членам (пары или братья и сестры)

Мои самые большие заблуждения:

  • Если я хочу добавить столбец с Clubописанием владельца, который также будет участником, каков наилучший подход, если один и тот же член не будет указан дважды?

  • Должен ли я поставить все свои таблицы на автоматическое увеличение идентификатора или это будет плохая идея? (Преимущества / недостатки?)

  • Если я добавлю внешние ключи на вкладку внешних ключей, будут ли они автоматически соответствовать правильной таблице или я должен добавить их также в столбцы? (см. рисунок 2)

  • И мой, пожалуй, самый неинтересный вопрос вообще ... Должен ли я поместить внешние ключи phonenumberи emailв их соответствующие таблицы, ссылающиеся на person_Id, или я должен поместить phoneNumber и email Id's в таблицу person?

(Мои извинения за то, что язык на фотографиях не является английским, я надеюсь, что это не слишком большая проблема)

дизайн

Внешние ключи

Vahx
источник

Ответы:

11

Ответы на ваши индивидуальные вопросы

Если я хочу добавить столбец с Clubописанием владельца, который также будет участником, каков наилучший подход, если один и тот же член не будет указан дважды?

Если - как указано в ваших спецификациях a Person can be a Member of only one Club- и вы заинтересованы в том, чтобы сохранить этот элемент данных просто как true или false , одним из вариантов является добавление столбца BIT(1)или BOOLEAN( TINYINT) в Personтаблицу, и вы можете вызвать этот столбец IsClubOwner. Таким образом, вы можете зарегистрировать тот факт, что определенный человек является владельцем клуба исключительно один раз. Кроме того, этот метод также позволяет сохранить несколько человек в качестве владельцев одного и того же клуба . Вы можете увидеть логическое описание этого подхода на рисунке 1 .

Тем не менее, вы ищете лучший подход, и, согласно моему опыту, такой подход влечет за собой разработку гораздо более расширяемой и универсальной структуры. В этом отношении выполните последовательность действий по моделированию для этих и других пунктов ниже в разделах, озаглавленных «Охват оставшихся спецификаций», «Лицо как член нескольких клубов» и «Член и владелец как отдельные типы сущностей».

Должен ли я поставить все мои таблицы на автоматическое увеличение idили это будет плохой идеей? (ПРЕИМУЩЕСТВА / минусы?)

Если вы сталкиваетесь с явным требованием, которое указывает определение таблицы со столбцом таких характеристик, и этот столбец имеет действительное контекстное значение или служит определенной цели, например, является суррогатом для широкого естественного ПЕРВИЧНОГО КЛЮЧА (PK), тогда да, Вы должны идти по этому пути.

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

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

Если я добавлю внешние ключи на вкладку внешних ключей, будут ли они автоматически соответствовать правильной таблице или я должен добавить их также в столбцы?

В связи с этим я советую вам создавать структуру базы данных вручную, кодировать свои собственные DDLзаявления, пока вы не получите четкое представление о предмете. Если вы сделаете это, вам будет легче понять процессы, которые графические инструменты выполняют «под капотом».

Для меня, например, создание заявления вроде следующего:

CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)

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

И мой, пожалуй, самый нудистый вопрос из всех ... Я помещаю внешние ключи phone_numberи emailв их соответствующие таблицы, ссылающиеся на person_idили я должен поместить phone_numberи email idsв таблицу лиц?

Лично я думаю, что этот и все другие ваши вопросы полностью актуальны и хорошо контекстуализированы .

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

  • A Person can be reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber can be used to reach one-to-many People

Таким образом, можно сделать вывод, что между многими существует взаимосвязь, Personи PhoneNumberпоэтому я предлагаю создать ассоциативную таблицу, названную PersonPhoneNumberдля представления указанных взаимосвязей в вашей базе данных. PK этой таблицы должен состоять из двух разных столбцов: PersonId(FOREIGN KEY [FK] указывает на Person.PersonId) и PhoneNumber(FK, который ссылается на PhoneNumber.Number). Логическое описание всего вышеперечисленного см. На рисунке 1 .

С другой стороны, давайте рассмотрим два следующих предложения:

  • A Person can be contacted via zero-one-or-many EmailAddresses
  • An EmailAddress can be used to contact exactly one Person

Затем, да, вы должны установить FK, ссылающийся Personна EmailAddressтаблицу, и эта таблица также должна иметь составной PK, который будет состоять из столбцов PersonIdи Address. Таким образом, вы можете убедиться в том , что та же комбинация EmailAddress.PersonIdи EmailAddress.Addressможет быть вставлен только один раз.

Если вы также хотите, чтобы данные EmailAddres.Addressмогли храниться в одной строке, вам просто нужно установить УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ для этого столбца.

Предлагаемые логические модели данных

Чтобы более четко изложить свои предложения, я включил четыре различные логические модели IDEF1X [1] , которые показаны на рис. 1 , рис. 2 , рис. 3 и рис. 4 . Я предоставлю объяснение наиболее важных функций, отображаемых в каждой из них в соответствующих разделах. Вы также можете скачать из Dropbox PDF, который объединяет в одной модели большинство обсуждаемых элементов.

Покрытие ваших оставшихся спецификаций

Отношения людей и адреса

Давайте рассмотрим два следующих (слегка перефразированных) утверждения, которые имеют отношение к людям и адресам :

  • A Person can only have one Address
  • An Address can belong to different People (couples or siblings)

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

Рис. 1. Модель данных клубов и членов - первые спецификации

Принимая во внимание указанную модель, необходимо выполнить следующие шаги:

  1. Создайте таблицу под названием PersonAddressфиксация отношений между Personи Address. Установите столбцы PersonIdи AddressIdв качестве составного ПК этой таблицы.

  2. Сконфигурируйте UNIQUE CONSTRAINT для PersonAddress.PersonIdстолбца, чтобы гарантировать, что конкретное значение может быть вставлено не более чем в одну строку указанной таблицы. На логическом уровне это обстоятельство подразумевает, что PersonAddress.PersonIdстал АЛЬТЕРНАТИВНЫМ КЛЮЧОМ [2] .

  3. Если значение AddressIdв определенной PersonAddressпопытке вставки еще не сохранено, то пусть вставка продолжается, в противном случае, когда такое значение уже существует в строке, вы должны проверить, что (a) PersonIdзарегистрированный пользователь AddressIdтакже зарегистрирован как Marriage.WifeIdесли PersonIdэто мужчина (данные, полученные с помощью Person.GenreCode) или (b), PersonIdто Marriage.HusbandIdкогда PersonIdэто женщина, (также полученная на основании Person.GenreCode). Если в соответствующей ситуации выполняется одно из этих условий, вам следует разрешить INSERT продолжить.

  4. Если вышеуказанные условия не были выполнены, есть шанс, что PersonAddressвставка будет успешной. Вы должны проверить, что PersonIdзначение, участвующее в указанной попытке вставки, делит хотя бы одно значение Progeny.ParentIdс тем PersonId, которое уже зарегистрировало PersonAddress.AddressId. Если это условие выполняется, то это означает, что они хранятся как Siblingsв базе данных, поэтому этот INSERT должен быть выполнен успешно.

Как и в любой реализации реляционной базы данных, вам следует серьезно подумать о выполнении ваших DMLопераций внутри транзакций ACID, чтобы вы могли защитить целостность и непротиворечивость данных, с которыми вы работаете.

Отвечая на требования, которые вы добавили в комментариях: Адреса и номера телефонов, служащие одинаково Клубам и Людям

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

В настоящем сценарии вы можете определить Personи Clubкак подтипы новой сущности, названной Party, термин, обычно используемый в юридических кругах для обозначения (а) человека или (б) группы лиц (как отмечено в смысле № 6 ). С помощью этого метода отношения между Addresses(или PhoneNumbers) и Peopleи Clubsбудут определены через Partyсупертип. См. Рисунок 2 для описания этого предложения.

Рис. 2. Модель данных клубов и членов - вторая спецификация

Сторона и адрес

Таким образом, мы можем прочитать в этой новой модели, что:

  • A Party keeps zero-one-or-many Addresses
  • An Address is kept by one-to-many Parties

Таким образом, существует много-ко-многим с участием Partyи Addressчто выражается путем PartyAddressсубъекта.

Вечеринка и номер телефона

Кроме того, мы можем интерпретировать это:

  • A Party is reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber is used by one-to-many Parties

Вот почему я добавил PartyPhoneNumberсущность, которая описывает связь «многие ко многим», которая действует между типами сущностей Partyи PhoneNumber.

Вечеринка и клуб или человек

Затем также можно прочитать, что:

  • A Party is either a Club or a Person

Следовательно, Partyпоставляет соединение из либо Clubs или People к Addresses(или PhoneNumbers).

Человек как член нескольких клубов

Как @aldwinaldwin упоминает в своем ответе, если вы хотите предоставить функциональность человеку, который будет членом нескольких клубов , то вы можете включить таблицу под названием ClubMember, которая будет выступать в качестве другого отношения многих ко многим, на этот раз, естественно, , соединяющий Personи Club.

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

Как показано на рисунке 3 , для такой таблицы требуется составной PK, состоящий из столбцов ClubIdи MemberId( которому присвоено имя роли [3]PersonId ), и эти столбцы должны быть определены также как FK, указывающие, соответственно, на Clubи Person.

Рис. 3. Модель данных клубов и членов - лицо как член нескольких клубов

Более адаптируемая структура

Используя этот параметр, вы также можете соблюдать первоначальное правило, которое гласит, что a Person can be a member of only one Clubвам нужно просто добавить УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ в MemberIdстолбец, чтобы определенное значение можно было ввести не более одного раза. Итак, как вы можете заметить, эта структура гораздо более адаптируема, чем та, что показана на рисунке 1 , поскольку, отбрасывая УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ (или ИНДЕКС), вы открываете вышеупомянутую функциональность, позволяющую человеку стать членом различных клубов на в то же время.

Член и владелец как отдельные типы объектов

Как вы знаете, хранение несколько фактов о роли осуществляется с помощью человека , как владелец из клуба -besides его лишь существования в истинном или ложном attribute- может быть очень выгодным. Например, вы можете сохранить дату вступления в силу , в которой определенный человек стал владельцем из клуба , следовательно , вы можете справиться с этой ситуацией, вводя отдельный тип объекта под названием ClubOwner, представленный на рисунке 4 .

Рис. 4. Модель данных клубов и участников - член и владелец как отдельные типы объектов

Как только вы построите таблицу на основе этого нового типа сущности, вы можете добавить подходящие столбцы, которые представляют характеристики, которые вступают в игру исключительно, когда a Personявляется Ownera of Club. Как изображено, эта таблица будет содержать PK, состоящий из ссылок на столбцы FK Person.PersonIdи Club.ClubId, таким образом, любую комбинацию ClubOwner.OwnerId(или ClubOwner.PersonId, если вы предпочитаете) и ClubOwner.ClubIdможет быть вставлена ​​только в одну возможность.

Конечно, с этой конфигурацией вы все еще можете получить в логической форме, если a Personявляется Ownerчастным Clubс помощью запроса, который возвращает скалярное значение, которое может быть оценено как true или false .


Ноты

1. Определение интеграции для информационного моделирования ( IDEF1X ) - это очень рекомендуемый метод моделирования данных, который был определен в качестве стандарта в декабре 1993 года Национальным институтом стандартов и технологий США ( NIST ). Оно прочно основано на (а) некоторые из теоретических работ , автором которого является отправителем в реляционной модели , т.е. д - р Ф. Кодда ; (б) теория сущностей-отношений , разработанная доктором П.П. Ченом ; а также о (c) методике проектирования логических баз данных , созданной Робертом Г. Брауном . Стоит отметить, что IDEF1X былформализован с помощью логики первого порядка .

2. ALTERNATE KEY - это атрибут (или комбинация атрибутов), который содержит значения, которые однозначно идентифицируют вхождение объекта, но не были выбраны в качестве PK соответствующего типа объекта; каждый тип сущности может иметь ноль, один или несколько АЛЬТЕРНАТИВНЫХ КЛЮЧЕЙ. В модели IDEF1X они обозначены как «AK» плюс его соответствующий номер, например, AK1, AK2 и т. Д. Они обычно реализуются в структуре SQL DDL через УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ (или УНИКАЛЬНЫЙ ИНДЕКС ).

3. Имена ролей - это обозначения (или псевдонимы), присвоенные атрибутам FK, чтобы выразить значение, которое они имеют в рамках своей соответствующей сущности. Их использование рекомендуется с 1970 г. д-ром Коддом в его оригинальной работе под названием «Реляционная модель данных для больших общих банков данных» . Со своей стороны, IDEF1X - сохранение верности в отношении реляционных практик - также выступает за именование ролей.

MDCCL
источник
2
  1. Если владелец всегда является членом его клуба. Добавьте ownerId к Club-столу и поместите туда personId члена, который является владельцем.
  2. Автоинкремент ИД это хорошо. Вы можете добавить другое поле «код», там вы поместите код участника на клубную карту.
  3. Должно быть автоматически в порядке (я думаю)
  4. Поместите personId в телефонные номера и таблицу адресов электронной почты.

... Вы не можете быть членом нескольких клубов? Если можете, создайте таблицу ClubMember с clubId и personId. Таким образом, вы можете подключить человека к нескольким клубам.

aldwinaldwin
источник
1
Что если я хочу, чтобы в моем клубе был номер телефона aswel? я могу ввести номер clubIdтелефона также и оставить ноль или клуб или человека?
Vahx
Я не стал бы «перебирать» все объекты (нормализация данных). Просто положите 1 номер телефона в клубный стол. Нормализация хороша, но слишком большая нормализация может вызвать проблемы.
aldwinaldwin
1
но предположим, я хочу это сделать? Я возьму адрес в качестве примера, у члена есть адрес, но клубам также понадобится адрес
Vahx
1
Создайте адрес-запись и поместите addressId в клуб. Поскольку клуб имеет 1 адрес, член имеет 1 адрес. Для телефонных номеров необходимо указать personId в записи номера телефона, чтобы иметь 1 ко многим. ..... Вы можете сделать таблицу personPhoneNumber (personId, phonenumberId) + таблица clubPhoneNumber таблицы (clubId, phonenumberId), что делает его более многосвязным.
aldwinaldwin