6 min read

Create a n:m Relationship

1 Introduction

As already announced in my post Create a 1:m Relationship, we now come to the last general type of relationship between two tables that I would like to deal with here: a n:m relationship

2 The assumed Situation

Let’s assume that this time we are to set up a database for a university with information about the students and the teaching professors.

In our example with the school classes it was easier, because here a teacher was assigned to a certain class (1:m relationship). Since at universities a student can enrol in several courses at will, this type of relationship is somewhat more difficult, and cannot be solved with just two tables (students and professors).

I use the Modified Chen Notation (MC Notation) below.

If you can’t read/interpret the diagram accurately, read my post on Associative Entity where I explained this in detail.

To be even more precise, the diagram would have to look like this:

3 Setting up the database and the required tables

First, we set up the two tables Student and Professor.

Since I would like to have the output of SSMS always in English I use the following syntax.

SET LANGUAGE ENGLISH

How I create the database and the tables can be read in my post Create a Database.

CREATE DATABASE University;

USE University;


CREATE TABLE Student
    (Student_ID INT NOT NULL PRIMARY KEY,
    First_Name VARCHAR(100) NOT NULL,
    Last_Name VARCHAR(100) NOT NULL)
    ;

CREATE TABLE Professor
    (Professor_ID INT NOT NULL PRIMARY KEY,
    First_Name VARCHAR(100) NOT NULL,
    Last_Name VARCHAR(100) NOT NULL)
    ;

4 Connecting the two tables

As the two tables currently stand, we cannot connect them. In order to do this, we need a so-called Associative Table.

The name should be chosen in such a way that it is recognisable for which two entities this table was created. The Foreign Keys are then stored within the Associative Table.

As you can see from the diagram above, our Associative Table has one more attribute. It makes sense not to create a separate table for the ‘Study Subject’, but to store this attribute here in a meaningful way.

4.1 Create an Associative Table

Let’s create our Associative Table:

CREATE TABLE Stundent_Prof
    (StudentProf_ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    Professor_ID INT NOT NULL FOREIGN KEY REFERENCES Professor(Professor_ID),
    Student_ID INT NOT NULL FOREIGN KEY REFERENCES Student(Student_ID),
    Study_Subject VARCHAR(100) NOT NULL)
    ;

Compared to the other tables, I have added another field in this SQL statement which I would like to explain in more detail: IDENTITY

4.1.1 AUTO INCREMENT via SQL Server

Here again is the corresponding part from the previous SQL statement:

CREATE TABLE Stundent_Prof
    (StudentProf_ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    ...)
    ;

IDENTITY is also known as AUTO INCREMENT, which allows us to automatically generate a unique number when a new record is inserted into a table.

Depending on the database system used, the syntax is slightly different. We use an SQL server here with SSMS. Therefore, the syntax for AUTO INCREMENT here is IDENTITY.

4.1.2 AUTO INCREMENT via My SQL

As an example, the Syntax for My SQL would be:

CREATE TABLE Stundent_Prof
    (StudentProf_ID INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (StudentProf_ID),
    ...)
    ;

4.1.3 AUTO INCREMENT via Access

The Syntax for Access would be:

CREATE TABLE Stundent_Prof
    (StudentProf_ID NOT NULL AUTOINCREMENT PRIMARY KEY,
    ...)
    ;

4.2 Review of the created relationships

The underlying ERD now looks like this:

Let’s also have a look at the relationship of the tables under Views in SSMS. I have described how to do this here.

Using the key and infinity symbols we can see how the tables are connected.

If you want to see a representation via Oracle Data Modeler, check out this chapter of my post Oracle SQL Developer Data Modeler: ERDs from old Posts with Oracle Data Modeler

5 Filling the tables

We can do a quick check at this point to see if the tables created really exist.

SELECT * FROM Student
SELECT * FROM Professor 
SELECT * FROM Stundent_Prof

Perfect, then we start filling the tables with sample values.

Again, it is important to pay attention to the order of filling. The two tables Student and Professor can be filled simultaneously.

The foreign keys are stored in the Associative Table Student_Prof. It can only be filled when the corresponding primary keys (‘Student_ID’ and ‘Professor_ID’) are stored, as they are referenced.

INSERT INTO Student (Student_ID, First_Name, Last_Name) VALUES (1, 'Max', 'Steel')
INSERT INTO Student (Student_ID, First_Name, Last_Name) VALUES (2, 'Jessy', 'Williams')
INSERT INTO Student (Student_ID, First_Name, Last_Name) VALUES (3, 'Marc', 'Pike')
INSERT INTO Student (Student_ID, First_Name, Last_Name) VALUES (4, 'Emily', 'Taylor')
INSERT INTO Student (Student_ID, First_Name, Last_Name) VALUES (5, 'Alex', 'Smith')


INSERT INTO Professor (Professor_ID, First_Name, Last_Name) VALUES (1, 'Andrew', 'Evergreen')
INSERT INTO Professor (Professor_ID, First_Name, Last_Name) VALUES (2, 'John', 'Hope')

And now we can also fill the Associative Table:

INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (1, 1, 'Law')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (1, 2, 'Law')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (1, 3, 'Law')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (1, 4, 'Law')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (1, 5, 'Law')

INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (2, 1, 'History')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (2, 2, 'History')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (2, 3, 'History')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (2, 4, 'History')
INSERT INTO Stundent_Prof (Professor_ID, Student_ID, Study_Subject) VALUES (2, 5, 'History')

Have a look at the filled tables:

SELECT * FROM Student
SELECT * FROM Professor 
SELECT * FROM Stundent_Prof

6 Queries on the tables

Now we can start querying the tables.

Here is a simple query as we already know from the two previous posts:

SELECT * 
    FROM Stundent_Prof 
        JOIN Student 
            ON Stundent_Prof.Student_ID = Student.Student_ID
        JOIN Professor
            ON Stundent_Prof.Professor_ID = Professor.Professor_ID;

Here is a query in which we filter for the subject ‘Law’:

SELECT * 
    FROM Stundent_Prof 
        JOIN Student 
            ON Stundent_Prof.Student_ID = Student.Student_ID
        JOIN Professor
            ON Stundent_Prof.Professor_ID = Professor.Professor_ID
    WHERE Study_Subject = 'Law';

And here is another query where we want to know which data are all stored for the student with the Student_ID = 1.

SELECT * 
    FROM Stundent_Prof 
        JOIN Student 
            ON Stundent_Prof.Student_ID = Student.Student_ID
        JOIN Professor
            ON Stundent_Prof.Professor_ID = Professor.Professor_ID
    WHERE Student.Student_ID = 1;

Again, I am aware that these joins are not particularly beautiful. I will describe how to execute beautiful joins in a later post.

7 Conclusion

In this post I have shown how to set up an n:m relationship between two tables using an Associative Table and how to query on it.