A normalização de banco de dados pode ser resumida em uma frase: "Armazene o mesmo fato em um único lugar." A forma sistemática de fazer isso é 1NF → 2NF → 3NF.

Por que isso é importante? — Se a mesma informação estiver espalhada por várias linhas, no momento em que você corrige uma e esquece as outras, os dados entram em contradição. Isso é chamado de anomalia de atualização. Veja isso acontecer na prática abaixo.

Update Anomaly — Try It

Prof.A moved to Room 502. Click the cell to update it. Notice: you have to change every row — miss one and the data contradicts itself.

Before (unnormalized)
studentcourseinstructorofficegrade
S1 KimMATH101Prof.ARoom 301 ← clickA
S1 KimCS102Prof.BRoom 405B+
S2 LeeCS102Prof.BRoom 405A
S3 ParkMATH101Prof.ARoom 301 ← clickB
0/2 updated
After (3NF)
Instructorsinstructor_idinstructor_office
Prof.ARoom 502
Prof.BRoom 405
In 3NF, you update exactly 1 row in the Instructors table. Done.

Se o laboratório do Prof.A mudou, em uma tabela não normalizada você precisa corrigir manualmente as 2 linhas. Se esquecer ao menos uma, surge a contradição: "Prof.A está na Room 301 e na Room 502 ao mesmo tempo". Em uma tabela em 3NF, basta corrigir exatamente 1 linha.

Isso é, no fundo, toda a ideia da normalização — o resto são regras para decidir "em qual tabela cada coluna deve ficar para que cada fato seja armazenado em apenas um lugar".

Dependência funcional — o critério para decidir a normalização

A normalização analisa "de que esta coluna depende". Isso é chamado de dependência funcional.

Por exemplo, student_id → student_name significa: "se você souber o ID do aluno, o nome fica determinado".

No diagrama abaixo, observe as cores das setas:

  • Verde = depende da chave completa (correto)
  • Amarelo = depende apenas de parte da chave (dependência parcial → viola a 2NF)
  • Vermelho tracejado = depende passando por uma coluna não chave (dependência transitiva → viola a 3NF)
Functional Dependencies at a Glance

Enrollment(student_id, course_id, student_name, course_title, instructor_id, instructor_office, grade)

student_idPrimary Keycourse_idPrimary Keystudent_namecourse_titleinstructor_idinstructor_officegrade
Full dependency (on entire key)Partial dependency (on part of key)Transitive dependency (via non-key)

Eliminar as setas amarelas e vermelhas = dividir a tabela = normalizar.

1NF → 2NF → 3NF de uma vez só

Clique abaixo e veja, etapa por etapa, como a tabela vai sendo dividida. As células em vermelho indicam: "esta coluna não deveria estar aqui".

Normalization Step-by-Step
Everything in one table. Multiple values in one cell.
Enrollment
student_id 🔑student_namecoursesgrades
S1KimMATH101, CS102A, B+
S2LeeCS102A
S3ParkMATH101, CS102, PHY201B, A, A-
Problem: courses column has multiple values crammed into one cell.
Fix: Split into one row per student-course pair.

1NF: um valor por célula

Se você coloca vários valores em uma célula, como MATH101, CS102, fica ruim de buscar e impossível de fazer JOIN direito.

Regra: toda célula deve ser atômica (conter um único valor).

Colunas como phone1, phone2, phone3 têm o mesmo problema — você só escondeu os valores no nome das colunas.

2NF: remover dependências parciais

Em uma tabela com chave composta (student_id, course_id), student_name depende apenas de student_id. Ou seja, não depende da chave inteira, mas só de uma parte dela — isso é uma dependência funcional parcial.

Regra: toda coluna não chave deve depender da chave completa.

Se houver dependência parcial, essa coluna deve ser removida e colocada em uma tabela separada.

E se a chave tiver uma única coluna? Dependência parcial é impossível, então se estiver em 1NF, automaticamente também está em 2NF.

3NF: remover dependências transitivas

Na tabela Courses, instructor_office não depende diretamente de course_id (a chave). Ela depende pelo caminho course_id → instructor_id → instructor_office — ou seja, uma coluna não chave depende de outra coluna não chave. Isso é uma dependência transitiva.

Regra: colunas não chave devem depender somente da chave. Não podem depender passando por outra coluna não chave.

Solução: separar instructor_office em uma tabela Instructors.

Em vez de decorar, guarde uma pergunta

"Todo atributo não chave deve depender da chave, da chave inteira e de nada além da chave."

Essa frase resume tudo:

  • da chave = 1NF (o fato precisa poder ser identificado por uma chave)
  • da chave inteira = 2NF (depende da chave completa, não só de parte dela)
  • de nada além da chave = 3NF (depende diretamente da chave, sem passar por colunas não chave)

Se cair uma questão de normalização na prova, faça só esta pergunta: "De quem esta coluna depende? Da chave inteira, de parte da chave ou de uma coluna não chave?"

Erros comuns

"Chegar até 3NF já resolve tudo" — 3NF é um ótimo ponto de partida, não o ponto final. Em alguns casos, você pode precisar da BCNF, que é mais rigorosa. Em outros, pode optar por desnormalizar de propósito por desempenho.

"Quanto mais tabelas, melhor" — o objetivo da normalização não é aumentar o número de tabelas, e sim fazer com que "cada tabela seja responsável por um único tipo de fato". Se você dividir sem motivo real (sem uma relação de dependência que justifique isso), só vai deixar os JOINs mais complicados.

"Se é NoSQL, não precisa de normalização" — normalização é um termo usado no contexto de bancos relacionais, mas o problema de "manter consistência em dados duplicados" existe em qualquer DB. Mesmo ao desnormalizar, você precisa saber exatamente "do que está abrindo mão".

Faça uma checagem no seu próprio projeto

Escolha uma tabela do seu projeto e:

  1. Escreva qual é a chave.
  2. Verifique se cada coluna não chave depende da chave inteira ou só de parte dela. → Se for só de parte, viola a 2NF.
  3. Verifique se alguma coluna não chave depende de outra coluna não chave. → Se sim, viola a 3NF.

Só com esses 3 passos, você já consegue encontrar a maioria dos problemas de normalização.

Precisa de ajuda com um problema?

Envie sua pergunta e receba uma solução verificada, passo a passo, em segundos.

Abrir GPAI Solver →