Exemplos / Sistema escolar
Sistema escolar
O banco de dados de uma escola liga alunos e disciplinas pelas matrículas. Essa é a tabela associativa, e ela também guarda a nota. Os professores dão turmas de uma disciplina num período. A frequência depende da matrícula, com uma linha por aluno e por dia de aula.
Abaixo, o ErdDocs desenha este schema a partir do SQL, com todas as tabelas e relacionamentos. Na aba «Dicionário de dados» está a versão para imprimir, completa e grátis nesta página. O SQL fica mais abaixo.
Passe o mouse sobre uma tabela para destacar os relacionamentos e clique para fixá-los.
O que cada tabela faz
- students / teachersTabelas separadas. Alunos e professores só compartilham o nome. Os dados e o ciclo de vida são diferentes.
- coursesA disciplina da grade. CS-101 existe uma vez só, não importa quantas vezes seja oferecida.
- sectionsA turma é uma disciplina num período, com um professor. É nela que o aluno de fato entra.
- enrollmentsTabela associativa entre aluno e turma. Além das ligações, ela guarda a nota.
- attendanceDepende da matrícula por uma chave estrangeira composta. Não dá para registrar presença numa turma em que o aluno não está matriculado.
Decisões de modelagem que vale copiar
- Separar disciplina e turma é a base do schema. Se você matricula alunos direto nas disciplinas, tudo quebra assim que a disciplina é oferecida duas vezes. São dois períodos e dois professores, mas uma só coluna de nota, e já não fica claro a que ela se refere.
- A frequência referencia a matrícula por uma chave estrangeira composta (student_id, section_id). Assim o próprio banco recusa presença de aluno não matriculado.
- A nota aceita nulo em vez de ter valor padrão. Nota vazia quer dizer que o período ainda está em andamento, e não que o aluno tirou zero.
O SQL
Dialeto PostgreSQL. Este SQL já está na ferramenta acima, e você pode copiá-lo à vontade para o seu banco ou para uma migration.
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 'Código da disciplina, ex.: 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 'Uma disciplina oferecida num período por um professor; os alunos se matriculam em turmas, não em disciplinas';
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 até o fim do período';
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)
);Perguntas frequentes
Onde entram pais ou responsáveis?
Numa tabela guardians e numa associativa student_guardians. É um relacionamento muitos para muitos, porque irmãos compartilham responsáveis e um aluno pode ter vários.
Por que não colocar teacher_id em courses?
Porque a mesma disciplina é dada por professores diferentes em períodos diferentes. O professor pertence à turma, não à disciplina da grade.