Designing relationships around an inheritance structure

前端 未结 1 1873
清歌不尽
清歌不尽 2021-01-07 02:19

I have a conceptual question regarding how best to organise my database.

Currently I have four core tables users, teachers, students<

相关标签:
1条回答
  • 2021-01-07 02:41

    There is a similar question here using a Media supertype and adding subtypes of CD, VCR, DVD, etc.

    This is scalable in that in creating, say, a BluRay subtype, you create the table to contain the BluRay-specific data and add an entry to the MediaTypes table. No changes needed for existing data or code -- except, of course, to add the code that will work with BluRay data.

    In your case, Users would be the supertype table with Teachers and Students the subtype tables.

    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 )
    );
    

    The makeup of the Students table would be similar to the Teachers table.

    Since both teachers and students may employ other teachers and students, the table that contains this relationship would refer to the Users table.

    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 )
    );
    

    As I understand it, Notifications are grouped by employer:

    create table Notifications(
        EmployerID    int not null
        NotificationDate date,
        NotificationData varchar( 500 ),
        -- other notification data...,
        constraint FK_NotificationsEmployer foreign key( EmployerID )
            references Users( ID )
    );
    

    The queries should be simple enough. For example, if a user wanted to see all the notifications from his employer(s):

    select  e.EmployerID, n.NotificationDate, n.NotificationData
    from    Employment  e
    join    Notifications n
        on  n.EmployerID = e.EmployerID
    where   e.EmployeeID = :UserID;
    

    This is an initial sketch, of course. Refinements are possible. But to your numbered points:

    1. The Employment table relates employers to employees. The only check if to make user employers cannot employee themselves, but otherwise any user can be both an employee and employer.
    2. The Users table forces each user to be either a teacher ('T') or student ('S'). Only users defined as 'T' can be placed in the Teachers table and only users defined as 'S' can be placed in the Students table.
    3. The Employment table joins only to the Users table, not to both the Teachers and Students tables. But this is because both teachers and students can be both employers and employees, not for any performance reason. In general, don't worry about performance during the initial design. Your primary concern at this point is data integrity. Relational databases are very good with joins. If a performance issue should crop up, then fix it. Don't restructure your data to solve problems that do not yet exist and may never exist.
    4. Well, give this a try and see how it works.
    0 讨论(0)
提交回复
热议问题