«Расширить» отношения в реляционной базе данных - PullRequest
1 голос
/ 18 марта 2011

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

Для примера, скажем, у нас есть следующие упрощенные сущности:

  • User
  • Student (расширяет User)
  • Teacher (расширяет User)

Userсодержит атрибуты, которые применяются как к Student, так и к TeacherStudent, и Teacher содержат пользовательские атрибуты, которые являются уникальными для них.

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

User
-------------
User ID
First name
Last name
Student class
Teacher office no.
Teacher description
...

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

  • большинство строк будет содержать студентов с небольшим количеством учителей
  • у учителей будет гораздо больше уникальных столбцов, которые занимают место в строках учеников

Было бы более эффективно реплицировать отношения между сущностями:

User
-------------
User ID
First name
Last name
...


Student
-------------
User ID
Student class
...


Teacher
-------------
User ID
Teacher office no.
Teacher description
...

Итак, мои вопросы:

  1. Является ли вышеупомянутая проблема слишком серьезной, то есть мы должны оставить эффективность храненияв ядро ​​базы данных?
  2. Делает ли сущности на 3 таблицы все еще нормально с точки зрения нормализации?
  3. Если это не очень хороший подход, как бы вы порекомендовали рассматривать отношения "расширение" вреляционная база данных?

Спасибо.

1 Ответ

2 голосов
/ 18 марта 2011

Если пользователь не может быть одновременно учителем и учеником, то вы смотрите на простую проблему супертипа / подтипа.(Я использую супертип и подтип в смысле проектирования реляционных баз данных, а не в смысле объектно-ориентированного программирования.) Вы вправе хранить в «учениках» только эти атрибутыкоторые описывают учеников и хранят в «учителях» только те атрибуты, которые описывают учителей.

-- Supertype: users
create table users (
  user_id integer not null unique,
  user_type char(1) not null 
    check (user_type in ('T', 'S')),
  -- other user columns
  primary key (user_id, user_type)
);

-- Subtype: students
create table students_st (
  user_id integer not null,
  user_type char(1) not null default 'S'
    check (user_type = 'S'),
  locker_num integer not null unique 
    check (locker_num > 0),
  -- other student columns
  primary key (user_id, user_type),
  foreign key (user_id, user_type) 
    references users (user_id, user_type) 
    on delete cascade
);

-- Subtype: teachers
create table teachers_st (
  user_id integer not null,
  user_type char(1) not null default 'T'
    check (user_type = 'T'),
  office_num char(4),
  -- other teacher columns
  primary key (user_id, user_type),
  foreign key (user_id, user_type) 
    references users (user_id, user_type) 
    on delete cascade
);

create view teachers as 
select u.user_id,
       u.user_type,
       -- other user columns
       t.office_num
       -- other teacher columns
from users u
inner join teachers_st t on (u.user_id = t.user_id);

create view students as 
select u.user_id,
       u.user_type,
       -- other user columns
       s.locker_num
       -- other student columns
from users u
inner join students_st s on (u.user_id = s.user_id);

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

...