All templates

School Management Database Design

Design a school database schema — departments, teachers, courses, students, enrollments, and grades.

Use this template

What you get

  • Courses offered by departments and taught by teachers
  • Student-to-course many-to-many resolved via enrollment
  • Grades recorded against each enrollment, not the student

What this template is for

For developers, database designers, CS students, and school IT staff who need an ER diagram for a school or university management system — without opening a paid modeling tool. This school management database template gives you a ready-to-edit schema modeling every entity an academic system needs: departments, teachers belonging to departments, courses taught by those teachers, students, enrollments that link a student to a course for a specific term, and grades recorded against each enrollment. The student-to-course relationship is many-to-many, resolved cleanly through the enrollment table — the single most important design decision in this domain, and the one most beginners get wrong. Open it, rename entities to match your school (class vs section, enrollment vs registration), add the fields your system needs, and share the diagram with your team or hand it to a CS class as an assignment starter. Because it's an editable whiteboard rather than a database migration file, you can iterate the schema in minutes before writing a single line of SQL — exactly what you want before committing to a table structure. No signup, no install.

When to use this template

  • Design the database for a new K-12, university, or online school management system.
  • Model the many-to-many relationship between students and courses via an enrollment table.
  • Plan how grades attach to a specific enrollment rather than directly to a student.
  • Decide how teachers and courses connect to departments (and how prerequisites are modeled).
  • Document an existing school database for a new developer joining the team.
  • Use as an ER-diagram assignment starter in a database or software-engineering course.

How to use it

  1. 1Start with Department and link Teacher records to it (each teacher belongs to one department).
  2. 2Add a Course table referencing both a department and the teacher who teaches it.
  3. 3Add a Student table for the people enrolling.
  4. 4Add an Enrollment table linking a student to a course for a given term — never link students to courses directly.
  5. 5Add a Grade table recording the score and letter against each enrollment (not against the student).
  6. 6Add cardinality notes: a student has many enrollments; a course has many enrollments; each enrollment has one grade.

Quick example

School enrollment schema

Department (id, name, code)
| 1 offers many |
Course (id, department_id, teacher_id, title, credits)
| 1 enrolled as many |
Enrollment (id, student_id, course_id, term, enrolled_at)
| 1 graded by 1 |
Grade (id, enrollment_id, score, letter)

Related resources

How it compares to similar tools

K-12 class-based vs university section-based

In K-12, a student is assigned to a fixed class for the year — enrollment is largely static and the schema stays simple (Student → Class → Teacher). Universities split Course (the catalog entry) from Section (a specific offering with its own teacher, schedule, and capacity); enrollment points to a Section, not the Course. Pick K-12-style when the school runs on fixed year-long classes; pick university-style when the same course can run multiple sections a term. Getting this wrong upfront means expensive schema migrations later.

Enrollment table vs direct student-course link

The most common beginner mistake is a direct many-to-many link between Student and Course. It looks simpler on the ER diagram but can't carry the fields every real school needs — term, status (active / withdrawn), enrolled_at, and where grades attach. An Enrollment resolver table costs one extra entity and lets the schema grow naturally as requirements arrive. Always use an Enrollment table.

Grades on Enrollment vs grades on Student

It's tempting to give Student a `gpa` field or attach grades directly to the student. Don't. The same student can take the same course in different terms (retakes, gap years, transfers), and grades belong to a specific attempt — an Enrollment. Compute overall GPA from enrollments; store nothing precomputed on the student that isn't a stable identity attribute.

Single term vs multi-term / academic year

Small systems sometimes bake the current term into Enrollment without an Academic Term entity. That works until you need transcripts across years or per-term reports. Add a Term (or AcademicYear + Semester) entity once the system has to answer questions like 'GPA by term' or 'students enrolled in Fall 2026' — refactoring this in later is painful.

Common mistakes to avoid

  • Direct many-to-many between Student and Course

    Skipping the Enrollment resolver table looks cleaner in a first draft but breaks the moment you need to attach term, status, or grade to a specific enrollment. Fix: always model students-to-courses through an Enrollment table, even if the current requirements would fit in a direct M:N — the requirements will grow.

  • Attaching grades to the Student instead of the Enrollment

    Putting a grade on the Student row (or worse, on the Course row) can't handle retakes or the same course taken across terms. Fix: grades attach to Enrollment, one grade per enrollment. Overall GPA is derived, not stored.

  • Forgetting the term field on Enrollment

    An Enrollment table without a term column can only represent 'is enrolled right now'. It can't answer 'what did this student take in Spring 2025?' Fix: put a term (and optionally a status) column on Enrollment from day one — retro-fitting it later requires backfilling.

  • Not separating Course (catalog) from Section (offering)

    If teachers, rooms, or schedules can vary per term for the same course, a single Course row can't hold both catalog data and the specific term's teacher. Fix: split into Course (id, catalog_code, credits) and Section (id, course_id, teacher_id, term, room, capacity), and point Enrollment at the Section. Skip this only if the school runs one section per course per term forever.

Frequently asked questions

What tables should a school management database have?+

At minimum: Department, Teacher, Course, Student, Enrollment, and Grade. Enrollment is the resolver table linking students to courses for a specific term; Grade attaches to Enrollment. Optional but common: Section (a specific offering of a Course), Term / AcademicYear, Assignment and Submission (for a detailed gradebook), and Prerequisite (a Course-to-Course self relation).

Why do students and courses need an Enrollment table between them?+

Because the relationship is many-to-many (a student takes many courses; a course has many students) and it needs to carry data of its own — term, status, enrolled_at, and where grades attach. A direct M:N link can't carry that data. The Enrollment table also makes retakes possible: the same student can enroll in the same course across different terms as separate enrollment rows.

How should grades be stored?+

Grades attach to an Enrollment, not to a Student or a Course directly. One enrollment has one grade (or a small set of components in a detailed gradebook). Store the raw score plus a computed letter; derive GPA from the grades of all a student's enrollments rather than storing GPA on the Student. This lets retakes, appeals, and per-term GPA reporting work naturally.

How does a K-12 school schema differ from a university schema?+

K-12 assigns students to a fixed class for the year, so enrollment is nearly static: Student → Enrollment → Class. Universities split Course (the catalog) from Section (a specific offering this term with a teacher, schedule, and capacity), and enrollment points at the Section. K-12 keeps the schema simple; university schemas need Section and Term entities because the same course can run multiple times.

Can I export this ER diagram to SQL or use it for a real database?+

The template is a design tool — it shows entities, fields, and relationships so you (and your team) can agree on the model before writing SQL. Once the diagram is settled, translate it into CREATE TABLE statements in your target database (Postgres, MySQL, SQLite). The relationships map directly: 1-to-many becomes a foreign key on the many side; many-to-many becomes the Enrollment-style resolver table.

Start editing online

Open the template in CodePic, replace the sample nodes, and turn it into your own study board in a few minutes.

See examples: /templates/school-management-database-design/examples

More templates you might like