# Student enrollment (university) data model

> An example university student enrollment data model with ER diagram — students, programs, departments, courses and prerequisites, course sections in terms, instructors, enrollments and grades — with SQL DDL.

Source: https://entitymodel.com/docs/examples/student-enrollment/

This example models course registration at a university: students in degree programs, departments and their courses, prerequisites between courses, the sections of each course offered in a term and taught by an instructor, and students' enrollments with their grades.

## Design notes

- **A course is not a section.** `course` is the catalog entry (CS201, Data Structures, 4 credits); `course_section` is one offering in a term, with an instructor, a room and a capacity. Students enroll in sections.
- **Students and sections are many-to-many**, resolved by `enrollment`, which also holds the grade and status.
- **Prerequisites are a relationship from course to course**, resolved by `course_prerequisite` with a minimum grade.
- **Grades are a reference list with grade points**, so GPA can be calculated from the data.
- **Programs belong to departments and have a degree level**, so requirements and reporting follow the academic structure.

To extend it: add `classroom` and `meeting_time` for timetabling, `waitlist`, `tuition_invoice`, or `program_requirement` for degree audits.

## Diagram

Student Enrollment (University): 9 entities, 2 reference lists and 11 relationships. Each box is an entity with its attributes (PK marks the primary key); solid lines are relationships in crow's foot notation, dashed lines point to reference lists.

<!-- diagram -->

**[Open this model in EntityModel.com](https://entitymodel.com/#/share/v1.zVpbb-O4Ff4rBPuwLSp7Jec6fqpjyzNBc0PsfegWA4GWaJtYSdSSVKbuIP-9oERJpEQnsscZFJiHCUnz3L6PPOdQ3-GasgQJOIY4FUTsEhrhGDPoqIngBTNOaArHngM5zVmI4Rhuhcj4-Ndftd8MQ5pAB6YokQu4yCOcigCnjMZxglMBHSiIiOXkopwEfj0J_vpbSgpJYvc36EDKNigl_0WikAz9Qsx9JQbg_6AkizGHDowwDxnJ1MIJyOt9xkApwR2QMbphKOEOCGnOOObgGxFbkDHM8J854UTgeg5wHMrtOBAo32wFWO0ASblgeSgo44CkQGAm92qMU_ttGIowH0IH1l6D3tCFDkS52FLWNQU6kAskcg7HEGUZoy84gg4MGUYCR0ERmJE7uhx43sA9W7ruuPg3dF33d-jAPIt6rSviRDCH439_b4VI-pDwLEa7QE0s6okyvIHYZeUPUBohVuhHY8qCkEZy_C9n_uXkem4JRoYZpylAUUKEwBEQFIgt1mIkXYWEYGSVC6t2AZHiYrTCsQac25lEU6nV7cMSOpDwIGMkQWwX_IF3cCxYjh1YBJfhqPpb4Ub5yvXO4avTkZjmyaogQFvqQzWhJC-Wz7cPn2FXTJ6SP3Nc_ZUR0pW_sCiwzuO4jEEje57HMXgox9piCQ_UMru1VsEPFG3BP0miC8YJIrEm1Fd_n8DOlKLt8A-S_CNPybAa1kRL-AZ0HawIE1tNhRkSGDyuwY0aV6rMJksf7hE1ct2rgXs9cM90AYr5Jo6eykELjtommoie4TBGDEfVeSLh2yjgeYZTi8MBRwFNddeqUfCYdqx6G60D99PA9eDrV3liyLOooKXkzFcHIoZRg1RueBhniInEyvSZPteT7FeTi-m13yV7ClCIIpyQEDQi9_O7WWOGplHpBCy_sDuiTTJN5pFUa0ROaZLlAjOwCAlOQwPsq5zEEUk3muibZqgts9nzMxKYgy8ojt8O_0QFgFsI0A3-Uz3RM_Le_PLs8tJyzEd4wzCuSOEAnodbgDi4WYSg7Y_9iDiQqYdiwWRnJayFhErcD8PAZroJRumyIMYvOC4drMOxcOednAPTck5p8uzP_Wf_YeoH_sPydvmv4tRYY1ZsP_6uItnaX-ZTuchyEdSOh2OoiX5905LJ9MseGvUnbk-KVsuCkOGICK5t_6ymwLSe6inBG7lH0KbMBbusmVbjPUnzaXI-8VwLaVSyKbPJLQYhEiimmyHwUbgt8ktABCAc0LUMbyTpRFMMKAMJZU2Oup9O5f5mjErlT5E-eW7XWW0cK2kmgnsmE9qBuhi5nkVYWUx0pC3V8PHUnSGBwKIAS86wCYoOLA9G4_nHculInAd6JWS7KozZntA_n5zPLkb7oS-2SIAk5wKsMMgQ5zgCK7yW8EYpFVvMfiq6TS2XkpTlhkVpJ0mqflElNnvpoDszsGmq-xN8lNrVQrAmjLcU9kxKJSQlSZ4ERf2q6XlfjoPPavw9UmmsPQKKTZHdReCtPtcTf6P5xezqzIK_BMtCDtA1WKMwj8UOfNtSIDAKt5j3OFobRc2wNkqe4Ii9uvrpteETo-sh8GOcIvBMOSc_qUjEQyal7a0RPzDjaN8i-66P5ucTzmlIZHkq3YU5p-wIrMsbvovyZTnaE98X06v5p7crMSlmP47lrOlSqcCpuiujtr1t_BbCfjjTnqM4BlKg2ctBTASyuWD0cRATYFYOHlN668V91N7dT6Oj9vZGA-_6nbI-3OIoj2WZ2L251XFlaePVEz3xNPFGc--6g6dHmXbKLJSkG3lmIi11RQXCHK1TilKtWfpGe69UrtXeKwdPAMBPrjVn7Jcu9E57e_PnEKYcdbn0vUYqt7cy9crxe1L1A7ofMlkfTIyajhZd7rqOK_98r9nhuUaiHKIMhbKy1cLXDPV0xeU7daCdZsYLRotivj73o81y1X8GDG8IF0XRVzBMxcxp8tA1SVFcPjbsZ1ijt4kj7dFFx9HN7efjqHZ-4bre6Mw8fQ_q3R_WpT_s4Oh_RNT9WiRs_dqJaLZe3t77i-Xk_ukgbpQ3yfVg5C499Tzzu65AEc82M4vM-9gmUJXOW7o_mrDXNhT9JBM7kKeCKJBFZvEwGbSuWvl8ZVyz5cB7mWFLqvK0AyJGswxHstcRUilTtDXwH54f7-782eHd8MolLSJXBY7J4carndLWv5peTzskvsNC9vvKZ0CA0kjSlagBkFGSijfKit4A0A_mg7hqRq6UV2rVkfhUDVfJjD-9vZ_cyccXhkOinoRHDuQhknuPDqHC2fBq31lc-zx4QXGuHKR5Zgwn0DFVH8PzoVtezObCQXdlKbm98ubvtpVntpW2hTbhNxbhI6vwqW2hbctZd6FnXTjvLnSLhRb_BvWbvl-GByi_72lW2x6Rmnb1KSj0gmPZ9lSvCvvpYu2d25rmR9Ol3fouJbaqmFLijz8YyOZDTNkv_BBiaD4Yw8li8SgdqqmplauFIcb6wrzWcl2N9vr7yWLZXn-PZKpiWz17nHZWz6jMXwtlDoJisTguvgbhW5J1PhQgxacg9c-bLxsEYhssjFewELFI5k_lFfkw9spPXb4hFgV6rlLuybD8UgHXM18QB833ESsSEVbmHii2X2tt-H4tpGGySUsM6s9eGtRU2z9Y7XTDGitqw4zn3T62PaoHhZudxbxikp_IMrNv063G6Fq3rX5wOd60ZVmFWi1blt29jzZNaxFb7Ws32mtja_P7GPrcSAGPa4u1asGpzG3KZ-tjXaX6R9rKQf3ytsfYCMyL7vBpSGnt4O8p01PddqOLfTyW78setTW68hCal53rj8ZzVW5Zsdy0no4LbVW2WY2szqnJh4K4OmfNGO63T_VtDzlob1OLdarXcDKGVq0ovTtVnIatG2S_ZQZu_79OW7Ml1qnZjbvf_OC0Mq7JCPpY5tfbtu2q2wFFUE9hm9YrMU4XLUTv2NYJaR8TraCU54rR0jqJgU3DRuZxW4IZYuGW6MW6-m9K1R6v_wM)** to explore it, change it and export it. Nothing is uploaded: the model travels in the link. Or [download model.json](/docs/examples/student-enrollment/model.json).

## Entities

| Entity | Type | Description | Primary Key | Display Attribute | Attributes |
| --- | --- | --- | --- | --- | --- |
| Course | Entity | A course in the catalog. Each term it is offered as one or more sections. | course_id | course_title | 5 |
| Department | Entity | An academic department. | department_id | department_name | 3 |
| Enrollment | Entity | A student registered in a section, with the final grade. | enrollment_id | enrolled_at | 6 |
| Instructor | Entity | A member of faculty who teaches sections. | instructor_id | full_name | 5 |
| Prerequisite | Entity | A course that must be passed before another. | course_id | minimum_grade | 3 |
| Program | Entity | A degree program, such as BSc Computer Science. | program_id | program_name | 5 |
| Section | Entity | One offering of a course in a term, taught by an instructor. | section_id | section_code | 7 |
| Student | Entity | A person admitted to the university. | student_id | full_name | 7 |
| Term | Entity | An academic term. | term_id | term_name | 4 |
| Degree Level | Reference | Levels of degree. | level_code | level_name | 2 |
| Grade | Reference | Letter grades and their grade points. | grade_code | grade_points | 2 |

## Attributes

### Course

A course in the catalog. Each term it is offered as one or more sections.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| course_id | INT | PK, Required |  | 210 |  |
| course_code | STRING | Required |  | CS201 |  |
| course_title | STRING | Label, Required |  | Data Structures |  |
| credits | INT | Required |  | 4 |  |
| department_id | INT | Required |  | 5 |  |

### Department

An academic department.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| department_id | INT | PK, Required |  | 5 |  |
| department_name | STRING | Label, Required |  | Computer Science |  |
| building | STRING |  |  | Gates Hall |  |

### Enrollment

A student registered in a section, with the final grade.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| enrollment_id | BIGINT | PK, Required |  | 4500123 |  |
| student_id | INT | Required |  | 2026014 |  |
| section_id | INT | Required |  | 9001 |  |
| enrolled_at | TIMESTAMP | Label, Required |  | 2026-08-20T10:00:00Z |  |
| grade_code | REFERENCE |  | → grade.grade_code | A- | Empty until graded. |
| status | STRING | Required |  | ENROLLED | Enrolled, dropped or completed. |

### Instructor

A member of faculty who teaches sections.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| instructor_id | INT | PK, Required |  | 77 |  |
| full_name | STRING | Label, Required, PII |  | Prof. Elena Rossi |  |
| email | STRING | Required, PII |  | e.rossi@uni.example |  |
| department_id | INT | Required |  | 5 |  |
| title | STRING |  |  | Associate Professor |  |

### Prerequisite

A course that must be passed before another.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| course_id | INT | PK, Required |  | 210 | The course with the requirement. |
| prerequisite_course_id | INT | PK, Required |  | 101 | The course required first. |
| minimum_grade | STRING | Label |  | C |  |

### Program

A degree program, such as BSc Computer Science.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| program_id | INT | PK, Required |  | 11 |  |
| program_name | STRING | Label, Required |  | BSc Computer Science |  |
| degree_level_code | REFERENCE | Required | → degree_level.level_code | BACH |  |
| department_id | INT | Required |  | 5 |  |
| required_credits | INT | Required |  | 120 |  |

### Section

One offering of a course in a term, taught by an instructor.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| section_id | INT | PK, Required |  | 9001 |  |
| course_id | INT | Required |  | 210 |  |
| term_id | INT | Required |  | 202602 |  |
| instructor_id | INT | Required |  | 77 |  |
| section_code | STRING | Label, Required |  | CS201-A |  |
| room | STRING |  |  | Gates 104 |  |
| capacity | INT | Required |  | 60 |  |

### Student

A person admitted to the university.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| student_id | INT | PK, Required |  | 2026014 |  |
| student_number | STRING | Required, PII |  | S2026014 |  |
| full_name | STRING | Label, Required, PII |  | Noah Kim |  |
| email | STRING | Required, PII |  | noah.kim@uni.example |  |
| date_of_birth | DATE | PII |  | 2007-08-03 |  |
| program_id | INT | Required |  | 11 | Declared program. |
| enrolled_on | DATE | Required |  | 2026-09-01 |  |

### Term

An academic term.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| term_id | INT | PK, Required |  | 202602 |  |
| term_name | STRING | Label, Required |  | Fall 2026 |  |
| start_date | DATE | Required |  | 2026-09-01 |  |
| end_date | DATE | Required |  | 2026-12-18 |  |

### Degree Level

Levels of degree.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| level_code | STRING | PK, Required |  | BACH |  |
| level_name | STRING | Label, Required |  | Bachelor's |  |

### Grade

Letter grades and their grade points.

| Attribute | Data Type | Flags | Reference | Example | Description |
| --- | --- | --- | --- | --- | --- |
| grade_code | STRING | PK, Required |  | A- |  |
| grade_points | DECIMAL(12,2) | Label, Required |  | 3.70 |  |

## Relationships

| Relationship | Source | Target | Cardinality | Forward Label | Reverse Label | Key | Description |
| --- | --- | --- | --- | --- | --- | --- | --- |
| studies | Student | Program | N:1 | Studies | Has Student | student.program_id |  |
| offered_by | Program | Department | N:1 | Offered By | Offers | program.department_id |  |
| course_of | Course | Department | N:1 | Taught By | Teaches | course.department_id |  |
| requirement_of | Prerequisite | Course | N:1 | Requirement Of | Requires | course_prerequisite.course_id |  |
| required_course | Prerequisite | Course | N:1 | Requires Course | Required For | course_prerequisite.prerequisite_course_id |  |
| instructor_in | Instructor | Department | N:1 | Member Of | Has Faculty | instructor.department_id |  |
| section_of | Section | Course | N:1 | Section Of | Offered As | course_section.course_id |  |
| offered_in | Section | Term | N:1 | Offered In | Schedules | course_section.term_id |  |
| taught_by | Section | Instructor | N:1 | Taught By | Teaches | course_section.instructor_id |  |
| enrolls | Enrollment | Student | N:1 | Enrolls | Enrolled In | enrollment.student_id |  |
| in_section | Enrollment | Section | N:1 | In | Has Enrollment | enrollment.section_id |  |

## Reference data

### Degree Level

4 values · Source: Example values

| level_code | level_name |
| --- | --- |
| ASSOC | Associate |
| BACH | Bachelor's |
| MAST | Master's |
| DOCT | Doctorate |

### Grade

8 values · Source: Example values

| grade_code | grade_points |
| --- | --- |
| A | 4.00 |
| A- | 3.70 |
| B+ | 3.30 |
| B | 3.00 |
| B- | 2.70 |
| C | 2.00 |
| D | 1.00 |
| F | 0.00 |

## SQL DDL (PostgreSQL)

Generated from the model. In the app, Export → Code also writes MySQL, Snowflake and Databricks DDL, DBML, dbt `schema.yml` and data contracts.

```sql
-- Student Enrollment (University) — data model
-- PostgreSQL DDL, generated 2026-11-03
-- Made with EntityModel.com

-- Reference list: Grade
CREATE TABLE grade (
  grade_code TEXT NOT NULL,
  grade_points NUMERIC(12,2) NOT NULL,
  PRIMARY KEY (grade_code)
);
COMMENT ON TABLE grade IS 'Letter grades and their grade points.';

-- Reference list: Degree Level
CREATE TABLE degree_level (
  level_code TEXT NOT NULL,
  level_name TEXT NOT NULL,
  PRIMARY KEY (level_code)
);
COMMENT ON TABLE degree_level IS 'Levels of degree.';

CREATE TABLE student (
  student_id INTEGER NOT NULL,
  student_number TEXT NOT NULL,
  full_name TEXT NOT NULL,
  email TEXT NOT NULL,
  date_of_birth DATE,
  program_id INTEGER NOT NULL,
  enrolled_on DATE NOT NULL,
  PRIMARY KEY (student_id)
);
COMMENT ON TABLE student IS 'A person admitted to the university.';
COMMENT ON COLUMN student.program_id IS 'Declared program.';

CREATE TABLE department (
  department_id INTEGER NOT NULL,
  department_name TEXT NOT NULL,
  building TEXT,
  PRIMARY KEY (department_id)
);
COMMENT ON TABLE department IS 'An academic department.';

CREATE TABLE program (
  program_id INTEGER NOT NULL,
  program_name TEXT NOT NULL,
  degree_level_code TEXT NOT NULL,
  department_id INTEGER NOT NULL,
  required_credits INTEGER NOT NULL,
  PRIMARY KEY (program_id)
);
COMMENT ON TABLE program IS 'A degree program, such as BSc Computer Science.';

CREATE TABLE course (
  course_id INTEGER NOT NULL,
  course_code TEXT NOT NULL,
  course_title TEXT NOT NULL,
  credits INTEGER NOT NULL,
  department_id INTEGER NOT NULL,
  PRIMARY KEY (course_id)
);
COMMENT ON TABLE course IS 'A course in the catalog. Each term it is offered as one or more sections.';

CREATE TABLE course_prerequisite (
  course_id INTEGER NOT NULL,
  prerequisite_course_id INTEGER NOT NULL,
  minimum_grade TEXT,
  PRIMARY KEY (course_id, prerequisite_course_id)
);
COMMENT ON TABLE course_prerequisite IS 'A course that must be passed before another.';
COMMENT ON COLUMN course_prerequisite.course_id IS 'The course with the requirement.';
COMMENT ON COLUMN course_prerequisite.prerequisite_course_id IS 'The course required first.';

CREATE TABLE instructor (
  instructor_id INTEGER NOT NULL,
  full_name TEXT NOT NULL,
  email TEXT NOT NULL,
  department_id INTEGER NOT NULL,
  title TEXT,
  PRIMARY KEY (instructor_id)
);
COMMENT ON TABLE instructor IS 'A member of faculty who teaches sections.';

CREATE TABLE term (
  term_id INTEGER NOT NULL,
  term_name TEXT NOT NULL,
  start_date DATE NOT NULL,
  end_date DATE NOT NULL,
  PRIMARY KEY (term_id)
);
COMMENT ON TABLE term IS 'An academic term.';

CREATE TABLE course_section (
  section_id INTEGER NOT NULL,
  course_id INTEGER NOT NULL,
  term_id INTEGER NOT NULL,
  instructor_id INTEGER NOT NULL,
  section_code TEXT NOT NULL,
  room TEXT,
  capacity INTEGER NOT NULL,
  PRIMARY KEY (section_id)
);
COMMENT ON TABLE course_section IS 'One offering of a course in a term, taught by an instructor.';

CREATE TABLE enrollment (
  enrollment_id BIGINT NOT NULL,
  student_id INTEGER NOT NULL,
  section_id INTEGER NOT NULL,
  enrolled_at TIMESTAMP NOT NULL,
  grade_code TEXT,
  status TEXT NOT NULL,
  PRIMARY KEY (enrollment_id)
);
COMMENT ON TABLE enrollment IS 'A student registered in a section, with the final grade.';
COMMENT ON COLUMN enrollment.grade_code IS 'Empty until graded.';
COMMENT ON COLUMN enrollment.status IS 'Enrolled, dropped or completed.';

-- Keys between tables
ALTER TABLE student ADD CONSTRAINT uq_student_student_number UNIQUE (student_number);
ALTER TABLE student ADD CONSTRAINT uq_student_email UNIQUE (email);
ALTER TABLE course ADD CONSTRAINT uq_course_course_code UNIQUE (course_code);
ALTER TABLE instructor ADD CONSTRAINT uq_instructor_email UNIQUE (email);
ALTER TABLE program ADD CONSTRAINT fk_program_degree_level_code FOREIGN KEY (degree_level_code) REFERENCES degree_level (level_code);
ALTER TABLE enrollment ADD CONSTRAINT fk_enrollment_grade_code FOREIGN KEY (grade_code) REFERENCES grade (grade_code);
ALTER TABLE student ADD CONSTRAINT fk_studies FOREIGN KEY (program_id) REFERENCES program (program_id);
ALTER TABLE program ADD CONSTRAINT fk_offered_by FOREIGN KEY (department_id) REFERENCES department (department_id);
ALTER TABLE course ADD CONSTRAINT fk_course_of FOREIGN KEY (department_id) REFERENCES department (department_id);
ALTER TABLE course_prerequisite ADD CONSTRAINT fk_requirement_of FOREIGN KEY (course_id) REFERENCES course (course_id);
ALTER TABLE course_prerequisite ADD CONSTRAINT fk_required_course FOREIGN KEY (prerequisite_course_id) REFERENCES course (course_id);
ALTER TABLE instructor ADD CONSTRAINT fk_instructor_in FOREIGN KEY (department_id) REFERENCES department (department_id);
ALTER TABLE course_section ADD CONSTRAINT fk_section_of FOREIGN KEY (course_id) REFERENCES course (course_id);
ALTER TABLE course_section ADD CONSTRAINT fk_offered_in FOREIGN KEY (term_id) REFERENCES term (term_id);
ALTER TABLE course_section ADD CONSTRAINT fk_taught_by FOREIGN KEY (instructor_id) REFERENCES instructor (instructor_id);
ALTER TABLE enrollment ADD CONSTRAINT fk_enrolls FOREIGN KEY (student_id) REFERENCES student (student_id);
ALTER TABLE enrollment ADD CONSTRAINT fk_in_section FOREIGN KEY (section_id) REFERENCES course_section (section_id);

-- Reference values
INSERT INTO grade (grade_code, grade_points) VALUES
  ('A', 4.00),
  ('A-', 3.70),
  ('B+', 3.30),
  ('B', 3.00),
  ('B-', 2.70),
  ('C', 2.00),
  ('D', 1.00),
  ('F', 0.00);

INSERT INTO degree_level (level_code, level_name) VALUES
  ('ASSOC', 'Associate'),
  ('BACH', 'Bachelor''s'),
  ('MAST', 'Master''s'),
  ('DOCT', 'Doctorate');
```

## Mermaid

Paste into a `mermaid` code block on GitHub, GitLab or Notion to show the diagram there.

```mermaid
---
title: Student Enrollment (University)
---
%% Made with EntityModel.com
erDiagram
  student {
    int student_id PK "Student ID"
    string student_number "Student Number"
    string full_name "Full Name"
    string email "Email"
    date date_of_birth "Date Of Birth"
    int program_id FK "Declared program."
    date enrolled_on "Enrolled On"
  }
  department {
    int department_id PK "Department ID"
    string department_name "Department Name"
    string building "Building"
  }
  program {
    int program_id PK "Program ID"
    string program_name "Program Name"
    string degree_level_code FK "Degree Level Code"
    int department_id FK "Department ID"
    int required_credits "Required Credits"
  }
  course {
    int course_id PK "Course ID"
    string course_code "Course Code"
    string course_title "Course Title"
    int credits "Credits"
    int department_id FK "Department ID"
  }
  course_prerequisite {
    int course_id PK, FK "The course with the requirement."
    int prerequisite_course_id PK, FK "The course required first."
    string minimum_grade "Minimum Grade"
  }
  instructor {
    int instructor_id PK "Instructor ID"
    string full_name "Full Name"
    string email "Email"
    int department_id FK "Department ID"
    string title "Title"
  }
  term {
    int term_id PK "Term ID"
    string term_name "Term Name"
    date start_date "Start Date"
    date end_date "End Date"
  }
  course_section {
    int section_id PK "Section ID"
    int course_id FK "Course ID"
    int term_id FK "Term ID"
    int instructor_id FK "Instructor ID"
    string section_code "Section Code"
    string room "Room"
    int capacity "Capacity"
  }
  enrollment {
    bigint enrollment_id PK "Enrollment ID"
    int student_id FK "Student ID"
    int section_id FK "Section ID"
    timestamp enrolled_at "Enrolled At"
    string grade_code FK "Empty until graded."
    string status "Enrolled, dropped or completed."
  }
  grade {
    string grade_code PK "Grade Code"
    decimal grade_points "Grade Points"
  }
  degree_level {
    string level_code PK "Level Code"
    string level_name "Level Name"
  }
  student }o--|| program : "Studies"
  program }o--|| department : "Offered By"
  course }o--|| department : "Taught By"
  course_prerequisite }o--|| course : "Requirement Of"
  course_prerequisite }o--|| course : "Requires Course"
  instructor }o--|| department : "Member Of"
  course_section }o--|| course : "Section Of"
  course_section }o--|| term : "Offered In"
  course_section }o--|| instructor : "Taught By"
  enrollment }o--|| student : "Enrolls"
  enrollment }o--|| course_section : "In"
  program }o..|| degree_level : "Degree Level Code"
  enrollment }o..|| grade : "Grade Code"
```

## Frequently asked questions

### How do you model students and courses in a database?

Students and courses are many-to-many, but enrollments are really in a course section (one offering of a course in a term). An enrollment table links student and course_section and stores the grade.

### How do you model course prerequisites?

With a course_prerequisite table that has two foreign keys to course: the course with the requirement and the course required first, optionally with a minimum grade.
