ErdDocs

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 を置かないのですか?

同じ科目を、学期によって別の教員が教えるからです。教員が属するのは科目マスタではなく開講クラスです。

ほかのサンプル