Browse Templates/School Management System

School Management System

A complete school management database schema designed for K-12 institutions and academies. Includes student and teacher profiles, class and subject management, grade recording with weighted scoring, and daily attendance tracking. Suitable for school ERP systems, academy management software, or custom school administration tools.

PostgreSQL10 tablesEducation
schoolstudentsteachersgradesattendanceeducation
Created with ERD Studio

About this schema

A subject and a class are not the same thing, and that distinction carries the schema. subjects is the curriculum entry — Mathematics, three credit hours. classes is one teacher teaching it in one semester in one room, with its own capacity. Grades and attendance key on the class, never on the subject, because what a student attended was a specific section.

The timetable is its own table because a class meets more than once a week. class_schedules holds a row per weekly slot with a day_of_week, a start and end time and its own room — so Monday in the lab and Wednesday in the lecture hall are two rows rather than an unrepresentable conflict.

attendance is one row per student per class per date. It is by far the largest table here, and it is a deliberate cost: nothing less than a row per session can answer which specific lesson a student missed, which is the question the whole attendance system exists for.

Key relationships

subjects → classes ← teachers
A class is a subject taught by one teacher in a given semester, which is what lets the same subject run as several sections.
classes → class_schedules
One row per weekly meeting, each with its own room, so a class that meets twice a week is two rows rather than a parsed string.
students → grades ← classes
exam_type on the row means midterm, final and coursework all coexist for the same student and class without extra columns.
students → attendance ← classes
Per student, per class, per date. The unique combination is what prevents a day being marked twice with different answers.
students → parents
Guardians hang off the student with a relationship, so a child can have two contactable guardians who are not themselves accounts.
departments ↔ teachers
A circular pair — the teacher belongs to a department and the department names a head_teacher_id, which must be nullable to be creatable at all.

Design decisions

classes sits between subjects and students

Attaching grades to a subject would be shorter and would merge every section of Mathematics into one. The class is what a timetable, a teacher assignment and a room all belong to, and two sections of the same subject are genuinely different courses to the students in them. The cost is an extra join on every academic query and the need to decide what happens to a class at the end of a semester.

Grades store both a score and a letter

The letter could be derived from the score on every read, and it would then change retroactively whenever the grading scale is adjusted. Storing grade_letter freezes the judgement made under the scale in force at the time, which is what a transcript requires. The duplication has to be written together, or the two columns will disagree about the same exam.

Parents are records, not accounts

The table holds a name, a relationship and contact details keyed to one student. That covers the only thing most school systems need — knowing who to call. It does not support a parent logging in to see two children, since each guardian row belongs to a single student. A parent portal is the point at which this becomes a parents table with a join.

Announcements use a nullable class_id

One table serves both the whole school and a single class: null means everyone. The alternative is two tables with identical columns and a union on every read of the noticeboard. The nullable key keeps it to one query, at the price of a filter that must be written correctly or a class notice reaches the entire school.

Tables in this template

studentsStudents
9 cols
parentsParents
7 cols
departmentsDepartments
5 cols
teachersTeachers
8 cols
subjectsSubjects
6 cols
classesClasses
7 cols
class_schedulesClass Schedules
6 cols
gradesGrades
7 cols
attendanceAttendance
6 cols
announcementsAnnouncements
8 cols

Frequently asked

How do I produce a student's timetable?
Find the classes the student is enrolled in and read their class_schedules rows, ordered by day_of_week and start_time. The per-slot room is on the schedule rather than the class, because a class can move rooms between sessions.
Why does attendance have a date column?
Because the record is per session, not per term. Without it there is no way to say which lesson was missed, and attendance becomes a single percentage that cannot be investigated or corrected.
Can a class have two teachers?
Not as modelled — classes has one teacher_id. Co-teaching needs a class_teachers join table, which is also where a role like assistant or lab supervisor would go.
Where is enrollment of students into classes?
It is implied by grades and attendance rather than stated. That is this schema's sharpest limitation: a student with no grades yet has no recorded link to the class, so a class_enrollments table is the first thing a working system needs.
How are different exam types weighted?
They are not — exam_type labels the row, but no weight is stored. Final-grade calculation therefore lives in application code, and moving it into the data means a weighting column per exam type or per class.