2015-10-06 3 views
1

У меня есть две таблицы, Teachers и Departments.Является ли это плохим дизайном базы данных?

Teachers работает в отделе, поэтому таблица преподавателей имеет внешний ключ department_id.

В каждом отделе есть один преподаватель в качестве его председателя. Поэтому Department имеет внешний ключ chairman, относящийся к таблице Teachers.

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

У меня есть два вопроса.

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

  2. Если нет, то как это сделать в базе данных?

+1

Как насчет ограничения внешнего ключа на обоих столбцах? 'ALTER TABLE dbo.Departments ADD CONSTRAINT FK_Chairman ИНОСТРАННЫЙ КЛЮЧ (ID, Teacher_ID) ССЫЛКИ dbo.Учителя (Department_ID, ID) ' – russianmario

+0

У меня есть две таблицы. «учителей» и кафедр. имеет иностранный ключ к отделу, а отдел имеет иностранный ключ к учителю. нет таблицы библиотеки – Anwar

+0

Yup, извините - мой плохой. – russianmario

ответ

1

В вашем проекте сделан ряд предположений.

  1. Учитель может быть только в одном отделе.
  2. В каждом отделе может быть только один председатель.
  3. Председатель - это единственная позиция, которую вы хотите сохранить.
  4. Вы не хотите больше ничего знать о председателе.
  5. Только учителя могут быть председателями.

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

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

CREATE TABLE staff (
    id INTEGER PRIMARY KEY, 
    name TEXT NOT NULL 
); 

CREATE TABLE departments (
    id INTEGER PRIMARY KEY, 
    name TEXT NOT NULL 
); 

CREATE TABLE department_roles (
    staff_id  INTEGER REFERENCES staff(id), 
    department_id INTEGER REFERENCES departments(id), 
    role   ENUM('chairman', 'teacher') 
); 

Этот макет гарантирует, что председатель находится в своем собственном отделе. Ограничения на department_roles могут приводить в действие бизнес-логику, например, иметь одного председателя на один отдел, или только преподаватели могут быть председателями, и их можно удалить или изменить позже, не затрагивая запросы. Это позволяет добавлять роли в будущем. Это позволяет добавлять дополнительную информацию к этим ролям. Это позволяет не учителям занимать должности департаментов.

+1

Кажется, мне было нужно много для многих. Благодаря! предположения 2,3,4 верны. Но учитель может взять класс другого отдела, но он работает (постоянно) только на одном факультете. и это одна информация необходима. – Anwar

+1

@Anwar Эти предположения верны * сейчас *, а как насчет позже? Перечисленные мной допущения являются всей бизнес-логикой, а не неотъемлемыми свойствами данных. Бизнес-логику следует применять с ограничениями, а не с реструктуризацией таблиц. Реструктуризация вызывает проблему совместимости запросов. – Schwern

+1

Спасибо. Ваш комментарий помог, а также ответ. :) – Anwar

1

вы должны думать об альтернативной конструкции: флаг учителя в качестве председателя («Y» для председателя и нуля для других) и сделать уникальный ключ на (department_id, председатель)

в оракуле: create unique index chairman_uq_idx on teacher(department_id, nvl(chairman, teacher_id))

в других DBS: create unique index chairman_uq_idx on teacher(department_id, chairman) where chairman is not null

есть 2 простые причины:

  1. циклические ссылки между таблицами всегда потенциальным источником неприятностей
  2. ORM подклассов - председатель специализация учителя
2

Это не плохой дизайн базы данных, так как с реляционной точки зрения, отношения прекрасны.

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

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

Если вы настаиваете на том, чтобы идти по этому пути, то комментарий rlb указывает на достойное решение. (Найдите другой комментарий в этом сообщении, который указывает на другое сообщение, которое показывает, как генерировать ошибку из триггера.)

+1

Спасибо. Ваш ответ помог мне устранить серьезную путаницу. Я всегда старался применять бизнес-правила для rdms! – Anwar

+3

Когда я говорю, что это философский вопрос, я имею в виду, что нет определенного ответа на него. Это открытый вопрос. Другие могут успешно утверждать, что вы должны применять любые отношения, о которых вы можете думать в СУБД. Послушайте, что говорят другие, кто-то может принести лучшие аргументы против того, что я предложил. –

+0

по крайней мере, хорошая идея отделить CRUD от BL слоя –

1

Как и в других сообщениях, существует несколько способов решения этой проблемы, и это когда вы на 100% уверены, что проблема действительно будет решена (см. Сообщение @ Шверна). Следующее, пожалуй, немного неудобно, но я использовал эту структуру для хорошего эффекта в подобных обстоятельствах.

стол Учитель выглядит следующим образом:

TEACHER 
TeacherId 
DepartmentId 

с ограничениями:

  • Первичный ключ на {TeacherId}
  • Уникальное ограничение на (TeacherId, DepartmentID}

Уникальный ограничение необходимо для следующего внешнего ключа.

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

DEPARTMENT 
DepartmentId 
ChairmanId 

с ограничениями:

  • Первичный ключ на {DepartmentID}
  • ограничение внешнего ключа на (ChairmanId, DepartmentID} в таблице УЧИТЕЛЯ, против уникальной ограничение

Вам нужно будет сделать хотя бы один из членов-председателей или преподавателей.Департме ntId NULLable, так как иначе вы никогда не сможете загружать данные.

Смежные вопросы