Има подобен въпрос тук използване на супертип Media и добавяне на подтипове CD, VCR, DVD и др.
Това е мащабируемо, тъй като при създаването, да речем, подтип BluRay, вие създавате таблицата, която да съдържа специфичните за BluRay данни и добавяте запис към таблицата MediaTypes. Не са необходими промени за съществуващи данни или код – освен, разбира се, добавяне на кода, който ще работи с BluRay данни.
Във вашия случай Потребителите ще бъдат таблицата за супертип, а Учителите и Учениците таблиците за подтипове.
create table Users(
ID int not null auto_generating,
Type char( 1 ) check( Type in( 'T', 'S' )),
-- other data common to all users,
constraint PK_Users primary key( ID ),
constraint UQ_UserType unique( ID, Type ),
constraint FK_UserTypes foreign key( Type )
references UserTypes( ID )
);
create table Teachers(
TeacherID int not null,
TeacherType char( 1 ) check( TeacherType = 'T' )),
-- other data common to all teachers...,
constraint PK_Teachers primary key( TeacherID ),
constraint FK_TeacherUser foreign key( TeacherID, TeacherType )
references Users( ID, Types )
);
Съставът на таблицата за ученици ще бъде подобен на таблицата на учителите.
Тъй като както учителите, така и учениците могат да наемат други учители и ученици, таблицата, която съдържа тази връзка, ще се отнася до таблицата Потребители.
create table Employment(
EmployerID int not null,
EmployeeID int not null,
-- other data concerning the employment...,
constraint CK_EmploymentDupes check( EmployerID <> EmployeeID ),
constraint PK_Employment primary key( EmployerID, EmployeeID ),
constraint FK_EmploymentEmployer foreign key( EmployerID )
references Users( ID ),
constraint FK_EmploymentEmployee foreign key( EmployeeID )
references Users( ID )
);
Както разбирам, известията са групирани по работодател:
create table Notifications(
EmployerID int not null
NotificationDate date,
NotificationData varchar( 500 ),
-- other notification data...,
constraint FK_NotificationsEmployer foreign key( EmployerID )
references Users( ID )
);
Запитванията трябва да са достатъчно прости. Например, ако потребител иска да види всички известия от своя работодател(и):
select e.EmployerID, n.NotificationDate, n.NotificationData
from Employment e
join Notifications n
on n.EmployerID = e.EmployerID
where e.EmployeeID = :UserID;
Това е първоначална скица, разбира се. Възможни са уточнения. Но към вашите номерирани точки:
- Таблицата за заетостта свързва работодателите със служителите. Единствената проверка дали да се направи потребител, работодателите не могат да наемат себе си, но в противен случай всеки потребител може да бъде едновременно служител и работодател.
- Таблицата „Потребители“ принуждава всеки потребител да бъде или учител („T“), или ученик („S“). Само потребители, дефинирани като „T“, могат да бъдат поставени в таблицата „Учители“, а само потребители, дефинирани като „S“, могат да бъдат поставени в таблицата „Студенти“.
- Таблицата „Заетост“ се присъединява само към таблицата „Потребители“, но не и към таблиците „Учители“ и „Ученици“. Но това е така, защото както учителите, така и учениците могат да бъдат както работодатели, така и служители, не поради някаква причина за представяне. Като цяло, не се притеснявайте за производителността по време на първоначалния дизайн. Вашата основна грижа в този момент е целостта на данните. Релационните бази данни са много добри с присъединяването. Ако трябва да възникне проблем с производителността, след което го поправете. Не преструктурирайте данните си, за да разрешите проблеми, които все още не съществуват и може никога да не съществуват.
- Е, опитайте и вижте как работи.