1

I am doing this exercise where I have to build an sql database (MySql) to store information on private lessons offered by teachers. These are the rules:

  • There is just one predifined week with slot times from Monday to Friday (15-19)
  • Each teacher can teach 1 or more courses
  • Each course can be teached by multiple teachers
  • One user can book just one lesson in a selected hour
  • One teacher can book just one lesson in a selected hour

This is how I implemented it:

USER(Name, Surname, Email (PK), Password)
TEACHER(Name, Surname, Email (PK), Password) 
COURSE(Title (PK))
SLOTTIME(Day (PK), Hour (PK))

TEACHES(EmailTeacher, TitleCourse) all attributes are PK, FK(EmailTeacher -> Teacher, TitleCourse -> Course)
BOOKING(EmailUser, EmailTeacher, TitleCourse, Day, Hour) all attributes are PK, FK((EmailUser -> User), 
(EmailTeacher, TitleCourse -> Teaches), (Day, Hour -> SlotTime))

This solution causes me two problems, or at least they are the ones I identified:

  1. I can have the same User booked with different Teacher and different Course at the same day and hour
  2. I can have the same User booked with the same Teacher at the same day and hour but with different Course

Here is an example:

BOOKING('raul@gmail.com', 'michael@gmail.com', 'Database I', 'Monday', 16) // FIRST INSERT
BOOKING('raul@gmail.com', 'anthony@gmail.com', 'Algorithms', 'Monday', 16) // DIFFERENT TEACHER AND COURSE
BOOKING('raul@gmail.com', 'michael@gmail.com', 'Database II', 'Monday', 16) // SAME TEACHER AND DIFFERENT COURSE

What I want to obtain is a table where the rules indicated above are respected, but I can't figure out how to implement it.

Raul
  • 135
  • 1
  • 12
  • Have you considered a unique constraint? – Gordon Linoff Nov 13 '20 at 12:08
  • What is the difference between Primary Key and Unique Constraint? – Raul Nov 13 '20 at 12:10
  • Personally, I find your choices for PK unsatisfactory. – Strawberry Nov 13 '20 at 12:10
  • @Raul In PK none part of the expression can be nullable. – Akina Nov 13 '20 at 12:20
  • @Akina all the attributes are not null, in all the tables – Raul Nov 13 '20 at 12:22
  • You have asked about the difference between PK and UI, so I have answered in general. In MySQL (for InnoDB at least) PK is clustered index also in addition to general difference. – Akina Nov 13 '20 at 12:25
  • @Akina; part of it *can* be nullable. It just can't be null !?!? Weird, right? – Strawberry Nov 13 '20 at 13:26
  • @Strawberry No. When we create a table with primary key or alter table adding PK then all columns mentioned in its expression and not defined as NOT NULL will be defined NOT NULL implicitly. When we alter table adding PK, and some nullable column mentioned in the PK expression contrans rows with NULL value then the statement will fail. [fiddle](https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=d10f713008d136467ee47ce0cf4a52d3) – Akina Nov 13 '20 at 14:53

2 Answers2

2

I would say you need a table for teacher bookings with a unique constraint on teacher and day hour. The constraint will prevent teachers from booking more than one hour at a time. Whether you want it to be the PK or not depends on your preferences, I personally dislike compound constraints (a PK is semantically also a unique constraint, but a unique constraint doesn't always need to be the PK).

BOOKING(EmailTeacher (PK), Day(PK), Hour(PK), TitleCourse) or 
BOOKING(ID (PK),  EmailTeacher, Day, Hour, TitleCourse)

With this setup I would rename your booking table to SUBSCRIPTION, to have two different names for two different entities (and make conversations about them easier). Boooking should be linked from Subscription and either from teacher or teaches (that raises a philosophical question ;) ).

On the SUBSCRIPTION table you need a unique constraint on (user,day, hour) to prevent users from booking more than one slot of the same interval.

SUBSCRIPTION(EmailUser(PK), EmailTeacher(PK), Day(PK), Hour(PK)) or
SUBSCRIPTION(EmailUser(PK), BookingId(PK))
Gabriel Xunqueira
  • 413
  • 1
  • 4
  • 11
  • In `SUBSCRIPTION` if I make (user, day, hour) UNIQUE the problem remains bacause I can have two Users with the same Teacher. Instead, making (teacher, day, hour) UNIQUE I can have a user booked with just one teacher at a time and viceversa, a teacher booked with one studente at a time. But I don't know if it's 100% correctly. – Raul Nov 14 '20 at 11:43
  • You didn't say lessons were limited to one student (user). In that case, in subscription you should make bookingId (whether the compound or simple version of it) unique. – Gabriel Xunqueira Nov 16 '20 at 13:27
1

Sort-out the logical design first, then go into details.

-- Teacher TCH exists.
--
teacher {TCH}
     PK {TCH}
-- Course CRS exists.
--
course {CRS}
    PK {CRS}
-- Time slot TIM exists.
--
slot {TIM}
  PK {TIM}
-- Teacher TCH teaches course CRS.
--
teacher_course {TCH, CRS}
            PK {TCH, CRS}

FK1 {TCH} REFERENCES teacher {TCH}
FK2 {CRS} REFERENCES course  {CRS}
-- Teacher TCH booked time slot TIM for course CRS.
--
teacher_slot_course {TCH, TIM, CRS}
                 PK {TCH, TIM}
                 SK {TCH, TIM, CRS}

FK1 {TCH, CRS} REFERENCES teacher_course {TCH, CRS}

FK2 {TIM} REFERENCES slot {TIM}
-- Student (user) USR exists.
--
user {USR}
  PK {USR}
-- Student USR signed-up for course CRS.
--
user_course {USR, CRS}
         PK {USR, CRS}

FK1 {USR} REFERENCES user    {USR}
FK2 {CRS} REFERENCES course  {CRS}
-- Student USR booked time slot TIM
-- for course CRS with teacher TCH.
--
user_slot_course_teacher {USR, TIM, CRS, TCH}
                      PK {USR, TIM}

        FK1 {USR, CRS} REFERENCES
user_course {USR, CRS}

                FK2 {TCH, TIM, CRS} REFERENCES
teacher_slot_course {TCH, TIM, CRS}

Note:

All attributes (columns) NOT NULL

PK = Primary Key
AK = Alternate Key   (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key
Damir Sudarevic
  • 21,891
  • 3
  • 47
  • 71
  • this works very well but I am undecided about one thing compared to the version of the first answer above. I'm going to use this database in a Java application, doesn't the schema with multiple tables make it slower to run, such as entering a user reservation? Second question :), if when I cancel a reservation I want to keep this data in the database, what is the best way to do it, I had thought of inserting it in a table containing only "old" data, but maybe there is some way not to waste memory. – Raul Nov 14 '20 at 17:46
  • @Raul: Short answer: no. The "extra table" `user_course` is a result of a different business logic -- asking a student to sign up for a course before booking a lesson from that course. Focusing on percieved performance problems during logical design will result in all kinds of trouble. In addition, the answer you are reffering to is open to all kinds of logical errors, mostly due to "... dislike compound constraints ...". Not even sure what that means. Take a look at: https://stackoverflow.com/questions/14588304/composite-primary-key-vs-additional-id-column – Damir Sudarevic Nov 15 '20 at 12:04