School System ER Diagram
The code
erDiagram
STUDENT ||--|{ ENROLLMENT : makes
COURSE ||--|{ ENROLLMENT : receives
TEACHER ||--o{ COURSE : teaches
ENROLLMENT ||--o{ GRADE : earns
STUDENT {
string name
date date_of_birth
}
COURSE {
string code
string title
int credits
}
ENROLLMENT {
date enrolled_on
string term
}
TEACHER {
string name
string department
}
How this template works
Schools are a perfect teaching ground for entity-relationship design because the interesting relationships are all many-to-many in disguise. Students take courses, courses are taught by teachers, and the grade lives on the enrollment rather than on the student or the course. This diagram captures that structure in four entities and four relationships.
Start with the join table. STUDENT ||--|{ ENROLLMENT : makes and COURSE ||--|{ ENROLLMENT : receives together express that a student takes many courses and a course holds many students, with ENROLLMENT as the meeting point. Because the enrollment is a real entity, it gets its own attribute block, holding date enrolled_on and string term, and it anchors the assessment data: ENROLLMENT ||--o{ GRADE : earns lets a single enrollment accumulate several graded pieces of work. TEACHER ||--o{ COURSE : teaches rounds out the picture with a plain one-to-many. Every attribute block follows the same two-column format, a type word and a name, such as int credits under COURSE.
The gotcha is putting data in the wrong entity. A grade belongs to the enrollment, not to the student, because the same student can take the same course in a different term and earn a different mark. If you find yourself wanting to draw a relationship straight from STUDENT to GRADE, you are usually one join table away from the cleaner model. Also keep entity names singular; STUDENTS and STUDENT will render as two unrelated boxes.
To grow the template, add a SEMESTER entity and link it to ENROLLMENT, extend GRADE with score and graded_at fields, or add a ROOM entity for scheduling. The pattern stays the same as the diagram grows: one line per relationship, one block per entity.
Related templates for comparison: the blog CMS ER diagram uses the same join-table trick for categories, the e-commerce ER diagram shows the pattern in a shop, and the employee management ER diagram applies it to staffing. The ER diagram guide has the complete symbol reference.
Variations to try
- Add a SEMESTER entity and link ENROLLMENT to it if terms need to be modeled explicitly.
- Extend GRADE with an attribute block showing score and graded_at fields.
- Add a ROOM entity and connect it to COURSE to schedule classes in physical spaces.