Bora ser um pouco detalhista aqui. Vamos passar passo a passo na criação da estrutura MANY-TO-MANY. Pronto?
Uma relação MANY-TO-MANY entre estudantes e cursos não rola direto numa tabela só. Um estudante pode se matricular em vários cursos, e um curso pode ter vários estudantes ao mesmo tempo.
Pra resolver isso, a gente cria uma tabela intermediária chamada enrollments, que vai guardar as infos das matrículas, tipo qual dupla estudante-curso existe. Isso deixa os dados certinhos e ainda facilita pra adicionar mais coisas, tipo a data da matrícula.
Como é a tabela enrollments?
Tu já sabe que a tabela enrollments vai ser o ponto central entre as tabelas students e courses. Olha só a estrutura dela:
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY, -- ID único do registro
student_id INT REFERENCES students(student_id), -- Foreign key pra tabela students
course_id INT REFERENCES courses(course_id), -- Foreign key pra tabela courses
enrollment_date DATE DEFAULT CURRENT_DATE -- Quando o estudante entrou no curso
);
Bora entender cada linha:
enrollment_id: É o identificador único de cada registro. Cada estudante matriculado num curso tem que ser único aqui.student_id: Mostra qual estudante tá matriculado. É uma foreign key que aponta pra tabelastudents(colunastudent_id).course_id: Mostra em qual curso o estudante tá matriculado. Essa coluna liga com a tabelacourses(colunacourse_id).enrollment_date: Um extra massa que mostra a data da matrícula. UsamosDEFAULT CURRENT_DATEpra já colocar a data de hoje quando criar o registro.
Criando as tabelas students e courses
Antes de ir pra frente, bora garantir que já temos as tabelas students e courses:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY, -- Identificador único do estudante
name TEXT NOT NULL, -- Nome do estudante
email TEXT NOT NULL UNIQUE -- Email do estudante, sem duplicidade
);
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY, -- Identificador único do curso
title TEXT NOT NULL, -- Nome do curso
description TEXT, -- Descrição do curso
start_date DATE -- Data de início do curso
);
Repara que aqui a gente colocou uns detalhes úteis, tipo email único pros estudantes e descrição do curso na tabela courses.
Ligando tudo junto
Agora que as tabelas tão prontas, bora criar a tabela enrollments:
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY, -- ID único da matrícula
student_id INT NOT NULL REFERENCES students(student_id), -- Foreign key
course_id INT NOT NULL REFERENCES courses(course_id), -- Foreign key
enrollment_date DATE DEFAULT CURRENT_DATE -- Data da matrícula
);
Inserindo dados nas tabelas
Beleza, as tabelas tão aí, mas tão vazias. Bora colocar uns estudantes, cursos e as matrículas:
Inserindo estudantes:
INSERT INTO students (name, email)
VALUES
('Alex Lin', 'alex.lin@example.com'),
('Maria Chi', 'maria.chi@example.com'),
('Otto Song', 'otto.song@example.com');
Inserindo cursos:
INSERT INTO courses (title, description, start_date)
VALUES
('Fundamentos de programação', 'Curso pra quem tá começando a programar.', '2023-11-01'),
('Bancos de dados', 'Vamos aprender SQL e bancos de dados relacionais.', '2023-11-15'),
('Desenvolvimento web', 'Criando sites e aplicações web.', '2023-12-01');
Inserindo registros de matrículas:
INSERT INTO enrollments (student_id, course_id)
VALUES
(1, 1), -- Alex Lin em "Fundamentos de programação"
(1, 2), -- Alex Lin em "Bancos de dados"
(2, 2), -- Maria Chi em "Bancos de dados"
(3, 3); -- Otto Song em "Desenvolvimento web"
Aqui student_id e course_id batem com os IDs das tabelas certas.
Testando as relações com queries
Pegando todas as matrículas:
SELECT e.enrollment_id, s.name AS student_name, c.title AS course_title, e.enrollment_date
FROM enrollments e
JOIN students s ON e.student_id = s.student_id
JOIN courses c ON e.course_id = c.course_id;
Resultado:
| enrollment_id | student_name | course_title | enrollment_date |
|---|---|---|---|
| 1 | Alex Lin | Fundamentos de programação | 2023-11-01 |
| 2 | Alex Lin | Bancos de dados | 2023-11-01 |
| 3 | Maria Chi | Bancos de dados | 2023-11-01 |
| 4 | Otto Song | Desenvolvimento web | 2023-11-01 |
Desafio pra praticar sozinho
Tenta adicionar mais uns estudantes e cursos, e depois matricula eles na tabela enrollments. Por exemplo, coloca um curso "Aprendizado de máquina" e matricula 1 ou 2 estudantes lá. Usa a query de cima pra conferir o resultado.
Erros comuns que podem rolar
Quando mexe com foreign keys e tabelas intermediárias, tem umas pegadinhas que a galera cai direto:
Falta de registro na tabela mãe: Se tu tentar adicionar um registro em
enrollmentscomstudent_idoucourse_idque não existe nas tabelasstudentsoucourses, vai dar erro. A foreign key não deixa passar batido.Quebra de integridade ao deletar: Se tu apagar um estudante ou curso que já tá sendo usado na tabela
enrollments, e não tiverON DELETE CASCADEconfigurado, vai dar ruim.Duplicação de registros: Confere pra não colocar o mesmo estudante no mesmo curso mais de uma vez, a não ser que isso faça sentido pro teu sistema.
Agora tu já tem um modelo massa pra representar relação MANY-TO-MANY entre estudantes e cursos no PostgreSQL. Essa estrutura é super comum em apps reais, tipo sistemas de gestão de ensino, CRM e vários outros. Bora pra próxima aula!
GO TO FULL VERSION