Det finns en liknande fråga här använda en mediasupertyp och lägga till undertyper av CD, VCR, DVD, etc.
Detta är skalbart genom att när du skapar, säg, en BluRay-undertyp, skapar du tabellen för att innehålla BluRay-specifika data och lägger till en post i MediaTypes-tabellen. Inga ändringar behövs för befintlig data eller kod -- förutom, naturligtvis, att lägga till koden som fungerar med BluRay-data.
I ditt fall skulle användare vara supertyptabellen med lärare och elever undertyptabellerna.
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 )
);
Uppsättningen av elevbordet skulle likna Lärarbordet.
Eftersom både lärare och elever kan anställa andra lärare och elever, skulle tabellen som innehåller denna relation hänvisa till tabellen Användare.
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 )
);
Som jag förstår det grupperas meddelanden efter arbetsgivare:
create table Notifications(
EmployerID int not null
NotificationDate date,
NotificationData varchar( 500 ),
-- other notification data...,
constraint FK_NotificationsEmployer foreign key( EmployerID )
references Users( ID )
);
Frågorna bör vara enkla nog. Till exempel, om en användare vill se alla meddelanden från sin(a) arbetsgivare:
select e.EmployerID, n.NotificationDate, n.NotificationData
from Employment e
join Notifications n
on n.EmployerID = e.EmployerID
where e.EmployeeID = :UserID;
Detta är förstås en första skiss. Förfinningar är möjliga. Men till dina numrerade punkter:
- Tabellen Sysselsättning relaterar arbetsgivare till anställda. Den enda kontrollen om att göra användaren arbetsgivare kan inte anställa sig själva, men annars kan alla användare vara både anställd och arbetsgivare.
- Tabellen Användare tvingar varje användare att vara antingen lärare ('T') eller elev ('S'). Endast användare definierade som 'T' kan placeras i tabellen Lärare och endast användare som definieras som 'S' kan placeras i tabellen Elever.
- Anställningstabellen ansluter endast till tabellen Användare, inte till både Lärare och Elever. Men det beror på att både lärare och elever kan vara både arbetsgivare och anställda, inte av någon prestationsskäl. I allmänhet, oroa dig inte för prestanda under den första designen. Ditt primära bekymmer vid denna tidpunkt är dataintegritet. Relationsdatabaser är mycket bra med joins. Om ett prestandaproblem bör dyka upp och åtgärda det sedan. Omstrukturera inte dina data för att lösa problem som ännu inte finns och kanske aldrig finns.
- Tja, prova det här och se hur det fungerar.