Моделирование наследования в базе данных - PullRequest
5 голосов
/ 06 января 2009

Для назначения базы данных мне нужно смоделировать систему для школы. Часть требований заключается в моделировании информации для сотрудников, учащихся и родителей.

В диаграмме классов UML я смоделировал это как эти три класса, являющиеся подтипами типа человека. Это потому, что всем им потребуется информация, в частности, об адресных данных.

Мой вопрос: как мне смоделировать это в базе данных (mysql)?

Пока мысли таковы:

  1. Создайте таблицу монолитных персон, которая содержит всю информацию для каждого типа и будет иметь множество нулевых значений в зависимости от того, какой тип хранится. (Я сомневаюсь, что с лектором это пошло бы хорошо, если бы я не аргументировал дело очень убедительно).
  2. Таблица персон с тремя внешними ключами, которые ссылаются на подтипы, но два из которых будут нулевыми - на самом деле, я даже не уверен, имеет ли это смысл или возможно?
  3. В соответствии с этой вики-страницей о django можно реализовать первичный ключ для подтипов следующим образом:

    "id" integer NOT NULL PRIMARY KEY REFERENCES "supertype" ("id")
  4. Что-то еще, о чем я не думал ...

Так что для тех, кто моделировал наследование в базе данных раньше; как ты это сделал? Какой метод вы рекомендуете и почему?

Ссылки на статьи / сообщения в блогах или предыдущие вопросы приветствуются.

Спасибо за ваше время!

UPDATE

Хорошо, спасибо всем за ответы. У меня уже была отдельная таблица адресов, так что это не проблема.

Приветствия

Адам

Ответы [ 8 ]

5 голосов
/ 06 января 2009

4 стола сотрудников, учеников, родителей и человека для родовых вещей. У сотрудников, учащихся и родителей есть специальные ключи, каждый из которых ссылается на Персона (а не наоборот).

У лица есть поле, в котором указывается подкласс этого человека (т. Е. Персонал, ученик или родитель).

РЕДАКТИРОВАТЬ:

Как указывает HLGM, адреса должны существовать в отдельной таблице, так как любой человек может иметь несколько адресов. (Однако - я собираюсь не согласиться с самим собой - вы можете намеренно ограничить количество адресов одним на человека, ограничивая выбор списков рассылки и т. Д.).

2 голосов
/ 06 января 2009

Я бы пошел на № 3.

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

И вам необязательно это расширение django (ПЕРВИЧНЫЙ КЛЮЧ ... ССЫЛКИ ...). Для этого вы можете использовать обычный КЛЮЧ ОТ ИНОГИ.

2 голосов
/ 06 января 2009

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

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

Ваши варианты:

  • 1) Одна таблица со всеми данными, имеющая столбец «разделитель». В этой колонке указывается, что это за человек. Это жизнеспособно в простых сценариях и (серьезно) высокой производительности, когда объединения будут слишком больно
  • 2) Таблица для каждого класса, которая приведет к дублированию столбцов, но будет избегать повторных объединений, поэтому она проста и на несколько секунд быстрее (хотя в большинстве сценариев это только уменьшает значение и индексацию).
  • 3) «Правильное» наследование. Нормализованная версия. Вы почти там, но ваш ключ находится не в том месте, ИМО. Ваша таблица Employee должна содержать PersonId, чтобы вы могли затем сделать:

    выберите employee.id, person.name из сотрудника внутреннего объединения на employee.personId = person.personId

Получить все имена сотрудников, имена которых указаны только в таблице персон.

1 голос
/ 06 января 2009

"Так что для тех, кто моделировал наследование в базе данных раньше; как вы это сделали? Какой метод вы рекомендуете и почему? «

Методы 1 и 3 хороши. Различия в основном в том, каковы ваши варианты использования.

1) адаптивность - что легче изменить? Несколько отдельных таблиц с отношениями FK к родительской таблице.

2) производительность - что требует меньше соединений? Один столик.

Крысы. Ни один дизайн не выполняет оба.

Кроме того, есть третий дизайн в дополнение к вашей мон-таблице и FK-to-parent.

Три отдельные таблицы с некоторыми общими столбцами (обычно копирование и вставка столбцов суперкласса среди всех таблиц подклассов). Это очень гибкий и простой в работе. Но для объединения общего списка требуется объединение трех таблиц.

0 голосов
/ 12 февраля 2013

Супер тип Персона должна быть создана следующим образом:

CREATE  TABLE Person(PersonID int primary key, Name varchar ... etc ...)

Все подтипы должны быть созданы следующим образом:

CREATE  TABLE IF NOT EXISTS Staffs(StaffId INT NOT NULL ,
  PRIMARY KEY (StaffId) ,  
  CONSTRAINT FK_StaffId FOREIGN KEY (StaffId) REFERENCES Person(PersonId)
  )

CREATE  TABLE IF NOT EXISTS Students(StudentId INT NOT NULL ,
  PRIMARY KEY (StudentId) ,  
  CONSTRAINT FK_StudentId FOREIGN KEY (StudentId) REFERENCES Person(PersonId)
  )

CREATE  TABLE IF NOT EXISTS Parents(PersonID INT NOT NULL ,
  PRIMARY KEY (PersonID ) ,  
  CONSTRAINT FK_PersonID  FOREIGN KEY (PersonID ) REFERENCES Person(PersonId)
  )

Внешний ключ в подтипах сотрудников, студентов, родителей добавляет два условия:

  1. Строка Person не может быть удалена, если соответствующая строка подтипа не будет не быть удаленным. Например, если в учениках есть одна запись таблица, ссылающаяся на таблицу Person, без удаления записи ученика запись человека не может быть удалена, что очень важно. Если студент объект создается тогда без удаления объекта Student мы не можем удалить базовый объект Person.

  1. Все базовые типы имеют внешний ключ "не ноль", чтобы убедиться, что каждая база тип будет иметь базовый тип, существующий всегда. Например, Если вы создаете Объект ученик, вы должны сначала создать объект Person.
0 голосов
/ 07 января 2009

Я предлагаю пять таблиц Человек Ученик Штат сотрудников родитель Адрес

ПОЧЕМУ - потому что у людей может быть несколько адресов, и у людей также может быть несколько ролей, а информация, которую вы хотите получить для сотрудников, отличается от информации, которую вы должны хранить для родителей или учеников.

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

Пожалуйста, прочитайте о нормализации, прежде чем пытаться создать базу данных. Вот источник для начала: http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelationalDatabaseDesign.aspx

0 голосов
/ 06 января 2009

«Правильный» ответ для целей задания, вероятно, № 3:

Person
PersonId Name Address1 Address2 City Country

Student
PersonId StudentId GPA Year ..

Staff
PersonId StaffId Salary ..

Parent
PersonId ParentId ParentType EmergencyContactNumber ..

Где PersonId всегда является первичным ключом, а также внешним ключом в последних трех таблицах.

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

0 голосов
/ 06 января 2009

Базы данных OO проходят ту же самую вещь и предлагают почти те же самые опции.

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

Если нет, вы можете подумать о создании системы, которая не использует наследование таким образом.

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

Хорошее правило - никогда не использовать наследование, если у вас нет кода, который по-разному работает с полем класса «Родитель», чем с тем же полем в классе «Дочерний». Если бизнес-код в вашем классе специально не ссылается на поле, это поле не должно вызывать наследование.

Но опять же, если вы в школе, это может не соответствовать тому, чему они пытаются научить ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...