CodeGym /Cursos /SQL SELF /Modelando relação MANY-TO-MANY usando uma tabela intermed...

Modelando relação MANY-TO-MANY usando uma tabela intermediária

SQL SELF
Nível 19 , Lição 4
Disponível

Relação "muitos-para-muitos" é quando um registro em uma tabela pode estar ligado a vários registros em outra tabela, e vice-versa. Por exemplo: - Um estudante (da tabela students) pode estar matriculado em vários cursos (da tabela courses). - Um curso pode ser frequentado por vários estudantes.

O problema é que guardar esse tipo de relação direto nas tabelas é bem chato. Por isso, a gente usa uma tabela intermediária, que armazena essas ligações.

Exemplo da vida real

Imagina que você criou uma tabela de estudantes e uma de cursos. Se tentar colocar em cada tabela uma coluna pra guardar todos os dados relacionados, vai virar bagunça:

  • Na tabela students você teria que guardar uma lista de todos os cursos em que o estudante está matriculado. Mas como guardar essa lista? Separado por vírgula? Em um array? Isso complica muito na hora de fazer query.
  • Na tabela courses teria que guardar a lista de estudantes, aí já viu, dor de cabeça total.

Então o jeito certo é criar uma terceira tabela, que vai guardar as ligações entre estudantes e cursos.

Tabela intermediária: nossa salvação!

A tabela intermediária (às vezes chamada de tabela de ligação) resolve tudo. Ela tem dois campos de referência externa:

  • Chave estrangeira pra tabela students.
  • Chave estrangeira pra tabela courses.

Cada registro nessa tabela cria uma ligação entre um estudante específico e um curso específico.

Criando tabelas pra relação "muitos-para-muitos"

Bora praticar! Olha só como a gente pode criar as tabelas pra ligar estudantes e cursos:

Passo 1: Criando a tabela students

Aqui está nossa tabela de estudantes. Guardamos os IDs únicos dos estudantes e os nomes deles.

CREATE TABLE students (
    student_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);
  • student_id — é o identificador único do estudante (auto-incrementado, valeu SERIAL!).
  • name — nome do estudante.

Passo 2: Criando a tabela courses

Agora vamos criar a tabela de cursos. Aqui guardamos os IDs únicos dos cursos e os nomes deles.

CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,
    title TEXT NOT NULL
);
  • course_id — identificador único do curso.
  • title — nome do curso.

Passo 3: Criando a tabela intermediária enrollments

Agora vamos criar nossa tabela mágica de ligação. Ela tem duas colunas, cada uma sendo uma chave estrangeira apontando pras tabelas certas.

CREATE TABLE enrollments (
    student_id INT REFERENCES students(student_id),
    course_id INT REFERENCES courses(course_id),
    PRIMARY KEY (student_id, course_id)
);

Bora entender a estrutura:

  • student_id — chave estrangeira apontando pro student_id da tabela students.
  • course_id — chave estrangeira apontando pro course_id da tabela courses.
  • PRIMARY KEY (student_id, course_id) — a chave primária é a combinação das duas chaves estrangeiras. Isso garante que cada ligação é única.

Inserindo dados

Bora colocar uns dados pra ver como funciona.

Passo 1: Adicionando estudantes

INSERT INTO students (name) VALUES
('Alice'),
('Bob'),
('Charlie');

Resultado:

student_id name
1 Alice
2 Bob
3 Charlie

Passo 2: Adicionando cursos

INSERT INTO courses (title) VALUES
('Mathematics'),
('History'),
('Biology');

Resultado:

course_id title
1 Mathematics
2 History
3 Biology

Passo 3: Adicionando registros em enrollments

Agora vamos matricular os estudantes nos cursos. Por exemplo:

  • Alice está matriculada em Mathematics e History.
  • Bob está só em Biology.
  • Charlie está em todos os três cursos.
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 1), -- Alice em Mathematics
(1, 2), -- Alice em History
(2, 3), -- Bob em Biology
(3, 1), -- Charlie em Mathematics
(3, 2), -- Charlie em History
(3, 3); -- Charlie em Biology

Resultado:

student_id course_id
1 1
1 2
2 3
3 1
3 2
3 3

Queries pra relação "muitos-para-muitos"

Agora que temos dados, bora tirar proveito disso!

Como achar todos os cursos em que um estudante está matriculado?

Por exemplo, pra saber em quais cursos a Alice (ID = 1) está matriculada, faz assim:

SELECT c.title
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
WHERE e.student_id = 1;

Resultado:

title
Mathematics
History

Como achar todos os estudantes matriculados em um curso específico?

Tipo, queremos saber quem está matriculado no curso Mathematics (ID = 1):

SELECT s.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
WHERE e.course_id = 1;

Resultado:

name
Alice
Charlie

Como achar estudantes e seus cursos?

Pra ver o panorama geral de quem está em qual curso, faz essa query:

SELECT s.name AS student, c.title AS course
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id;

Resultado:

student course
Alice Mathematics
Alice History
Bob Biology
Charlie Mathematics
Charlie History
Charlie Biology

A tabela enrollments deixa nosso esquema super flexível — dá pra adicionar ou remover ligações entre estudantes e cursos de boa, sem mexer nas tabelas principais. Com JOINs fica fácil achar o que quiser, tipo quem está em qual curso. E as chaves estrangeiras já garantem que não rola erro — tipo, ninguém vai conseguir matricular um estudante num curso que nem existe.

Erros comuns em relações "muitos-para-muitos"

Falta de restrição única: Se não colocar PRIMARY KEY, pode acabar adicionando a mesma ligação mais de uma vez sem querer.

Quebra de integridade dos dados: Tentar inserir um registro com student_id ou course_id que não existe vai dar erro.

Ordem errada ao deletar dados: Se deletar um curso da tabela courses antes, os registros em enrollments vão ficar "órfãos". Pra evitar isso, usa ON DELETE CASCADE na definição das chaves estrangeiras.

1
Pesquisa/teste
Chaves estrangeiras, nível 19, lição 4
Indisponível
Chaves estrangeiras
Chaves estrangeiras
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION