Eine ähnliche Frage gibt es hier Verwenden eines Medien-Supertyps und Hinzufügen von Untertypen von CD, VCR, DVD usw.
Dies ist insofern skalierbar, als Sie beispielsweise beim Erstellen eines BluRay-Untertyps die Tabelle erstellen, die die BluRay-spezifischen Daten enthält, und der MediaTypes-Tabelle einen Eintrag hinzufügen. Es sind keine Änderungen an vorhandenen Daten oder Code erforderlich – außer natürlich, um den Code hinzuzufügen, der mit BluRay-Daten funktioniert.
In Ihrem Fall wäre Users die Supertype-Tabelle und Teachers und Students die Subtype-Tabellen.
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 )
);
Der Aufbau der Tabelle „Students“ würde der Tabelle „Lehrer“ ähneln.
Da sowohl Lehrer als auch Schüler andere Lehrer und Schüler beschäftigen können, würde die Tabelle, die diese Beziehung enthält, auf die Benutzertabelle verweisen.
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 )
);
Soweit ich weiß, sind Benachrichtigungen nach Arbeitgeber gruppiert:
create table Notifications(
EmployerID int not null
NotificationDate date,
NotificationData varchar( 500 ),
-- other notification data...,
constraint FK_NotificationsEmployer foreign key( EmployerID )
references Users( ID )
);
Die Abfragen sollten einfach genug sein. Wenn ein Benutzer beispielsweise alle Benachrichtigungen von seinem/seinen Arbeitgeber(n) sehen möchte:
select e.EmployerID, n.NotificationDate, n.NotificationData
from Employment e
join Notifications n
on n.EmployerID = e.EmployerID
where e.EmployeeID = :UserID;
Dies ist natürlich eine erste Skizze. Verfeinerungen sind möglich. Aber zu Ihren nummerierten Punkten:
- Die Beschäftigungstabelle setzt Arbeitgeber mit Arbeitnehmern in Beziehung. Die einzige Prüfung, ob Benutzer zu Arbeitgebern gemacht werden sollen, kann sich nicht selbst beschäftigen, aber ansonsten kann jeder Benutzer sowohl Arbeitnehmer als auch Arbeitgeber sein.
- Die Benutzertabelle erzwingt, dass jeder Benutzer entweder ein Lehrer ('T') oder ein Schüler ('S') ist. Nur als „T“ definierte Benutzer können in die Teachers-Tabelle platziert werden und nur als „S“ definierte Benutzer können in die Students-Tabelle platziert werden.
- Die Tabelle „Employment“ wird nur mit der Tabelle „Users“ verknüpft, nicht mit den Tabellen „Teachers“ und „Students“. Dies liegt jedoch daran, dass sowohl Lehrer als auch Schüler sowohl Arbeitgeber als auch Arbeitnehmer sein können, nicht aus Leistungsgründen. Machen Sie sich während des anfänglichen Entwurfs im Allgemeinen keine Gedanken über die Leistung. Ihr Hauptanliegen an dieser Stelle ist die Datenintegrität. Relationale Datenbanken sind sehr gut mit Joins. Wenn Ein Leistungsproblem sollte auftauchen und es dann beheben. Strukturieren Sie Ihre Daten nicht um, um Probleme zu lösen, die noch nicht existieren und vielleicht nie existieren werden.
- Probieren Sie es aus und sehen Sie, wie es funktioniert.