ER図のサンプル / 学校管理システム
学校管理システム
学校のデータベースは、履修(enrollments)を通じて生徒と科目をつなぎます。履修は成績も持つ中間テーブルです。教員は学期ごとに科目の開講クラスを担当します。出欠は履修にぶら下がり、生徒ごと・授業日ごとに一行です。
下では、このスキーマのすべてのテーブルとリレーションを ErdDocs が SQL から描いています。「テーブル定義書」タブには印刷用の一覧があり、このページでは全体を無料で見られます。SQL はページ下部にあります。
スキーマ
テーブルにカーソルを合わせるとリレーションが強調され、クリックで固定できます。
各テーブルの役割
- students / teachers別テーブル。名前が同じなだけで、ライフサイクルもデータも違います。
- courses科目マスタ。CS-101 は何回開講されても一件です。
- sections開講クラスです。科目・学期・教員の組み合わせで、生徒が実際に参加する単位です。
- enrollments生徒と開講クラスの中間テーブルで、持っている値は成績です。
- attendance複合外部キーで履修にぶら下がります。履修していない授業に出席扱いされることはありません。
設計のポイント
- 科目と開講クラスの分離が、このスキーマの土台です。生徒を「科目」に履修させると、同じ科目が二回開かれた時点で破綻します(学期が二つ、教員が二人、成績カラムの意味がぶつかる)。
- 出欠は複合外部キー (student_id, section_id) で履修を参照します。履修していない生徒の出欠は、データベース自体が拒否します。
- 成績はデフォルト値を入れず NULL 許容にします。成績がないこと自体が情報(学期中)であって、0 点ではありません。
SQL
PostgreSQL の方言です。上のツール(すでに入っています)や、ご自身のデータベース、マイグレーションに自由にコピーして使えます。
CREATE TABLE students (
id bigserial PRIMARY KEY,
student_no varchar(20) NOT NULL UNIQUE,
full_name varchar(120) NOT NULL,
enrolled_on date NOT NULL
);
CREATE TABLE teachers (
id bigserial PRIMARY KEY,
full_name varchar(120) NOT NULL,
department varchar(80) NOT NULL
);
CREATE TABLE courses (
id bigserial PRIMARY KEY,
code varchar(12) NOT NULL UNIQUE,
title varchar(160) NOT NULL,
credits int NOT NULL
);
COMMENT ON COLUMN courses.code IS '科目コード(例:CS-101)';
CREATE TABLE sections (
id bigserial PRIMARY KEY,
course_id bigint NOT NULL REFERENCES courses(id),
teacher_id bigint NOT NULL REFERENCES teachers(id),
term varchar(20) NOT NULL,
room varchar(20)
);
COMMENT ON TABLE sections IS '開講クラス:ある学期に、ある教員が開く科目。生徒が履修するのは科目ではなく開講クラス';
CREATE TABLE enrollments (
student_id bigint NOT NULL REFERENCES students(id),
section_id bigint NOT NULL REFERENCES sections(id),
grade varchar(2),
PRIMARY KEY (student_id, section_id)
);
COMMENT ON COLUMN enrollments.grade IS '学期が終わるまでは NULL';
CREATE TABLE attendance (
student_id bigint NOT NULL,
section_id bigint NOT NULL,
class_date date NOT NULL,
present boolean NOT NULL,
PRIMARY KEY (student_id, section_id, class_date),
FOREIGN KEY (student_id, section_id) REFERENCES enrollments(student_id, section_id)
);よくある質問
保護者はどこに入れますか?
guardians テーブルと、中間テーブル student_guardians です。兄弟は保護者を共有し、生徒には複数の保護者がいるので多対多になります。
なぜ courses に teacher_id を置かないのですか?
同じ科目を、学期によって別の教員が教えるからです。教員が属するのは科目マスタではなく開講クラスです。