有一个类似的问题here 使用 Media 超类型并添加 CD、VCR、DVD 等的子类型。
这是可扩展的,例如在创建 BluRay 子类型时,您可以创建表以包含特定于 BluRay 的数据,并向 MediaTypes 表添加一个条目。现有数据或代码无需更改——当然,除了添加可用于蓝光数据的代码。
在您的情况下,用户将是超类型表,教师和学生是子类型表。
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 )
);
Students 表的构成类似于 Teachers 表。
由于教师和学生都可以雇用其他教师和学生,因此包含这种关系的表将引用用户表。
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;
当然,这是最初的草图。细化是可能的。但是对于您的编号:
- 就业表将雇主与雇员联系起来。唯一的检查是否使用户雇主不能雇用自己,否则任何用户都可以是雇员和雇主。
- Users 表强制每个用户是教师 ('T') 或学生 ('S')。只有定义为“T”的用户可以放置在教师表中,只有定义为“S”的用户可以放置在学生表中。
- Employment 表仅连接到 Users 表,而不连接到 Teachers 和 Students 表。但这是因为教师和学生都可以是雇主和雇员,而不是出于任何绩效原因。一般来说,在初始设计期间不要担心性能。此时您最关心的是数据完整性。关系数据库非常适合连接。 如果出现性能问题,请修复它。不要重组您的数据来解决尚不存在且可能永远不会存在的问题。
- 好吧,试试这个,看看它是如何工作的。