Pular para o conteúdo principal

Normalização em SQL (1NF - 5NF): Um guia para iniciantes

A normalização de bancos de dados é um processo importante usado para organizar e estruturar bancos de dados relacionais. Esse processo garante que os dados sejam armazenados de forma a minimizar a redundância, simplificar a consulta e melhorar a integridade dos dados.
Actualizado 30 de jul. de 2024  · 9 min de leitura

Neste artigo, exploraremos os conceitos básicos que você precisa saber sobre normalização, sua importância e as várias técnicas envolvidas. Este artigo é para, mas não se limita a, aqueles que desejam entrar no setor de dados.

O que é normalização no SQL?

A normalização, nesse contexto, é o processo de organização de dados em um banco de dados(banco de dados relacional) para eliminar anomalias de dados, como redundância.

Em termos mais simples, isso envolve a divisão de uma tabela grande e complexa em tabelas menores e mais simples, mantendo as relações de dados.

A normalização é comumente usada ao lidar com grandes conjuntos de dados.

Vamos dar uma breve olhada em alguns cenários em que a normalização é usada com frequência.

Integridade dos dados

Imagine um banco de dados que contém informações de clientes. Sem a normalização, se um cliente mudasse sua idade, precisaríamos atualizá-la em vários lugares, o que aumentaria o risco de inconsistências. Ao normalizar os dados, podemos ter tabelas separadas vinculadas por um identificador exclusivo que garantirá que os dados permaneçam precisos e consistentes.

Consulta de eficiência

Vamos considerar um banco de dados complexo com várias tabelas relacionadas que armazenam informações redundantes. Nesse cenário, as consultas que envolvem uniões se tornam mais complicadas e consomem muitos recursos. A normalização ajudará a simplificar a consulta, dividindo os dados em tabelas menores, com cada tabela contendo apenas informações relevantes, reduzindo assim a necessidade de uniões complexas.

Otimização do armazenamento

Um dos principais problemas dos dados redundantes é que eles ocupam espaço de armazenamento desnecessário. Por exemplo, se armazenarmos os mesmos detalhes do produto em cada registro de pedido, isso levará à duplicação. Com a normalização, você pode eliminar a redundância dividindo os dados em tabelas separadas.

Por que a normalização no SQL é importante?

A normalização desempenha um papel fundamental no design do banco de dados. Aqui estão vários motivos pelos quais isso é essencial:

  • Reduz a redundância: Redundância é quando a mesma informação é armazenada várias vezes, e uma boa maneira de evitar isso é dividir os dados em tabelas menores.
  • Melhora o desempenho da consulta: Você pode executar consultas mais rapidamente em tabelas menores que passaram por normalização.
  • Minimiza as anomalias de atualização: Com tabelas normalizadas, você pode atualizar facilmente os dados sem afetar outros registros.
  • Melhora a integridade dos dados: Isso garante que os dados permaneçam consistentes e precisos.

O que causa a necessidade de normalização?

Se uma tabela não estiver adequadamente normalizada e tiver redundância de dados, ela não só ocupará espaço extra de armazenamento de dados, mas também dificultará o manuseio e a atualização do banco de dados.

Há vários fatores que impulsionam a necessidade de normalização, desde a redundância de dados (conforme abordado acima) até a dificuldade de gerenciar relacionamentos. Vamos direto ao assunto:

  • Anomalias de inserção, exclusão e atualização: Qualquer forma de alteração em uma tabela pode levar a erros ou inconsistências em outras tabelas se você não for tratado com cuidado. Essas alterações podem ser a adição de novos dados a um banco de dados, a atualização dos dados ou a exclusão de registros, o que pode levar à perda não intencional de dados.
  • Dificuldade em gerenciar relacionamentos: Torna-se mais desafiador manter relacionamentos complexos em uma estrutura não normalizada.
  • Outros fatores que impulsionam a necessidade de normalização são as dependências parciais e as dependências transitivas, nas quais as dependências parciais podem levar à redundância de dados e a anomalias de atualização, e as dependências transitivas podem levar a anomalias de dados. Nas próximas seções, veremos como essas dependências podem ser tratadas para garantir a normalização do banco de dados.

Diferentes tipos de normalização de banco de dados

Até agora, vimos o que é normalização em SQL, por que a normalização em SQL é importante e o que causa a necessidade de normalização. A normalização do banco de dados vem em diferentes formas, cada uma com níveis crescentes de organização de dados.

Nesta seção, discutiremos brevemente os diferentes níveis de normalização e, em seguida, os exploraremos mais profundamente na próxima seção.

normalização do banco de dados

Imagem do autor

Primeira forma normal (1NF)

Esse nível de normalização garante que cada coluna dos seus dados contenha apenas valores atômicos. Valores atômicos, nesse contexto, significam que cada entrada em uma coluna é indivisível. É como dizer que cada célula de uma planilha deve conter apenas uma informação. O 1NF garante a atomicidade dos dados, com cada célula de coluna contendo apenas um único valor e cada coluna com nomes exclusivos.

Segunda forma normal (2NF)

Elimina dependências parciais, garantindo que os atributos que não são chaves dependam apenas da chave primária. O que isso significa, em essência, é que deve haver uma relação direta entre cada coluna e a chave primária, e não entre outras colunas.

Terceira forma normal (3NF)

Remove as dependências transitivas, garantindo que os atributos que não são chaves dependam apenas da chave primária. Esse nível de normalização se baseia em 2NF.

Forma Normal de Boyce-Codd (BCNF)

Essa é uma versão mais rigorosa do 3NF que aborda outras anomalias. Nesse nível de normalização, cada determinante é uma chave candidata.

Quarta forma normal (4NF)

Esse é um nível de normalização que se baseia no BCNF, lidando com dependências multivaloradas.

Quinta Forma Normal (5NF)

O 5NF é o nível de normalização mais alto que aborda as dependências de união. Ele é usado em cenários específicos para minimizar ainda mais a redundância, dividindo uma tabela em tabelas menores.

Normalização de banco de dados com exemplos do mundo real

Já destacamos todos os níveis de normalização de dados. Vamos explorar cada um deles com mais profundidade, com exemplos e explicações.

Normalização da primeira forma normal (1NF)

O 1NF garante que cada célula da coluna contenha apenas valores atômicos. Imagine um banco de dados de biblioteca com uma tabela que armazena informações sobre livros (título, autor, gênero e borrowed_by). Se a tabela não estiver normalizada, borrowed_by poderá conter uma lista de nomes de mutuários separados por vírgulas. Isso viola o 1NF, pois uma única célula contém vários valores. A tabela abaixo é uma boa representação de uma tabela que viola 1NF, conforme descrito anteriormente.

título

autor

genre

emprestado_por

Para matar um pássaro

Harper Lee

Ficção

John Doe, Jane Doe, James Brown

O Senhor dos Anéis

J. R. R. Tolkien

Fantasia

Emily Garcia, David Lee

Harry Potter e a Pedra Filosofal

J.K. Rowling

Fantasia

Michael Chen

A solução?

No 1NF, criamos uma tabela separada para os mutuários e os vinculamos à tabela de livros. Essas tabelas podem ser vinculadas usando a chave estrangeira na tabela do mutuário ou uma tabela de vinculação separada. A chave estrangeira na abordagem da tabela de mutuários envolve a adição de uma coluna de chave estrangeira à tabela de mutuários que faz referência à chave primária da tabela de livros. Isso imporá uma relação entre as tabelas, garantindo a consistência dos dados.

Você pode encontrar uma representação disso abaixo:

Tabela de livros

book_id (PK)

título

autor

genre

1

Para matar um pássaro

Harper Lee

Ficção

2

O Senhor dos Anéis

J. R. R. Tolkien

Fantasia

3

Harry Potter e a Pedra Filosofal

J.K. Rowling

Fantasia

Tabela de mutuários

borrower_id (PK)

nome

book_id (FK)

1

John Doe

1

2

Jane Doe

1

3

James Brown

1

4

Emily Garcia

2

5

David Lee

2

6

Michael Chen

3

Segunda forma normal (2NF)

Esse nível de normalização, conforme já descrito, baseia-se no 1NF, garantindo que não haja dependências parciais na chave primária. Em termos mais simples, todos os atributos que não são chaves devem depender de toda a chave primária e não apenas de parte dela.

A partir do 1NF que foi implementado, já temos duas tabelas separadas (você pode verificar a seção 1NF).

Agora, digamos que você queira vincular essas tabelas para registrar os empréstimos. A abordagem inicial pode ser simplesmente adicionar uma coluna borrower_id à tabela de livros, como mostrado abaixo:

book_id (PK)

título

autor

genre

borrower_id (FK)

1

Para matar um pássaro

Harper Lee

Ficção

1

2

O Senhor dos Anéis

J. R. R. Tolkien

Fantasia

NULL

3

Harry Potter e a Pedra Filosofal

J.K. Rowling

Fantasia

6

Isso pode parecer uma solução, mas viola o 2NF simplesmente porque o borrower_id depende apenas parcialmente do book_id. Um livro pode ter vários tomadores de empréstimo, mas um único borrower_id só pode ser vinculado a um livro nessa estrutura. Isso cria uma dependência parcial.

A solução?

Precisamos obter o relacionamento muitos-para-muitos entre livros e tomadores de empréstimos para obter 2NF. Você pode fazer isso introduzindo uma tabela separada:

Tabela Book_borrowings

borrowing_id (PK) book_id (FK) borrower_id (FK) borrowed_date
1 1 1 2024-05-04
2 2 4 2024-05-04
3 3 6 2024-05-04

Essa tabela estabelece uma relação clara entre livros e tomadores de empréstimos. O book_id e o borrower_id funcionam como chaves estrangeiras, fazendo referência às chaves primárias em suas respectivas tabelas. Essa abordagem garante que o borrower_id dependa de toda a chave primária (book_id) da tabela books, em conformidade com 2NF.

Terceira forma normal (3NF)

O 3NF baseia-se no 2NF, eliminando as dependências transitivas. Uma dependência transitiva ocorre quando um atributo não-chave depende de outro atributo não-chave, que, por sua vez, depende da chave primária. Basicamente, seu significado vem da lei transitiva.

Com base no 2NF que já implementamos, há três tabelas em nosso banco de dados de bibliotecas:

Tabela de livros

book_id (PK)

título

autor

genre

1

Para matar um pássaro

Harper Lee

Ficção

2

O Senhor dos Anéis

J. R. R. Tolkien

Fantasia

3

Harry Potter e a Pedra Filosofal

J.K. Rowling

Fantasia

Tabela de mutuários

borrower_id (PK)

nome

book_id (FK)

1

John Doe

1

2

Jane Doe

1

3

James Brown

1

4

Emily Garcia

2

5

David Lee

2

6

Michael Chen

3

Tabela Book_borrowings

borrowing_id (PK)

book_id (FK)

borrower_id (FK)

borrowed_date

1

1

1

2024-05-04

2

2

4

2024-05-04

3

3

6

2024-05-04

A estrutura 2NF parece eficiente, mas pode haver uma dependência oculta. Imagine que você adicione uma coluna due_date à tabela de livros. Isso pode parecer lógico à primeira vista, mas criará uma dependência transitiva em que você pode ter que se preocupar com o que está acontecendo:

  • A coluna due_date depende do borrowing_id (um atributo não-chave) da tabela book_borrowings.
  • O borrowing_id, por sua vez, depende do book_id (a chave primária) da tabela books.

A implicação disso é que due_date depende de um atributo intermediário não-chave (borrowing_id) em vez de depender diretamente da chave primária (book_id). Isso viola o 3NF.

A solução?

Você pode mover a coluna due_date para a tabela mais apropriada, atualizando a tabela book_borrowings para incluir as colunas due_date e returned_date.

Abaixo você encontra a tabela atualizada:

borrowing_id (PK)

book_id (FK)

borrower_id (FK)

borrowed_date

due_date

1

1

1

2024-05-04

2024-05-20

2

2

4

2024-05-04

2024-05-18

3

3

6

2024-05-04

2024-05-10

Ao colocar a coluna due_date na tabela book_borrowing, você eliminou com sucesso a dependência transitiva.

Isso significa que a due_date agora depende diretamente da relação combinada entre book_id e borrower_id. Nesse contexto, book_id e borrower_id estão agindo como uma chave estrangeira composta, que, juntos, formam a chave primária da tabela book_borrowings.

Forma Normal de Boyce-Codd (BCNF)

O BCNF é baseado em dependências funcionais que consideram todas as chaves candidatas em um relacionamento.

As dependências funcionais (FD) definem as relações entre os atributos em um banco de dados relacional. Um FD afirma que o valor de uma coluna determina o valor de outra coluna relacionada. Os FDs são muito importantes porque orientam o processo de normalização, identificando dependências e garantindo que os dados sejam distribuídos adequadamente pelas tabelas.

BCNF é uma versão mais rígida de 3NF. Isso garante que todo determinante (um conjunto de atributos que identificam exclusivamente uma linha) em uma tabela seja uma chave candidata (um conjunto mínimo de atributos que identificam exclusivamente uma linha). A essência disso é que todos os determinantes devem ser capazes de servir como chaves primárias.

Isso garante que cada dependência funcional (FD) tenha uma superchave como seu determinante. Em outras palavras, se X -> Y (X determina Y) for válido, X deverá ser uma chave candidata (superchave) da relação. Observe que X e Y são colunas em uma tabela de dados.

Como um acréscimo do 3NF, temos três tabelas:

Tabela de livros

book_id (PK)

título

autor

genre

1

Para matar um pássaro

Harper Lee

Ficção

2

O Senhor dos Anéis

J. R. R. Tolkien

Fantasia

3

Harry Potter e a Pedra Filosofal

J.K. Rowling

Fantasia

Tabela de mutuários

borrower_id (PK)

nome

book_id (FK)

1

John Doe

1

2

Jane Doe

1

3

James Brown

1

4

Emily Garcia

2

5

David Lee

2

6

Michael Chen

3

Tabela Book_borrowings

borrowing_id (PK)

book_id (FK)

borrower_id (FK)

borrowed_date

due_date

1

1

1

2024-05-04

2024-05-20

2

2

4

2024-05-04

2024-05-18

3

3

6

2024-05-04

2024-05-10

Embora a estrutura 3NF seja boa, pode haver um determinante oculto na tabela book_borrowings. Supondo que um mutuário não possa pegar o mesmo livro duas vezes ao mesmo tempo, a combinação de book_id e borrower_id identifica exclusivamente um registro de empréstimo.

Essa estrutura viola a BCNF, pois o conjunto combinado (book_id e borrower_id) não é a chave primária da tabela (que é apenas borrowing_id).

A solução?

Para obter o BCNF, podemos decompor a tabela book_borrowings em duas tabelas separadas ou tornar o conjunto de atributos combinados a chave primária.

  1. Abordagem 1 (decompor a tabela): Nessa abordagem, decomporemos a tabela book_borrowings em tabelas separadas:
    • Uma tabela com borrowing_id como chave primária, borrowed_date, due_date e returned_date.
    • Outra tabela separada para vincular livros e tomadores de empréstimo, com book_id como chave estrangeira, borrower_id como chave estrangeira e atributos potencialmente adicionais específicos do evento de empréstimo.
  1. Abordagem 2 (tornar o conjunto de atributos combinados a chave primária): Podemos considerar a possibilidade de tornar book_id e borrower_id uma chave primária composta para identificar exclusivamente os registros de empréstimos. O problema com essa abordagem é que ela não servirá ao seu propósito se um mutuário puder pegar o mesmo livro emprestado várias vezes.

No final, a escolha entre essas opções depende das suas necessidades específicas de dados e de como você deseja modelar os relacionamentos de empréstimo.

Quarta forma normal (4NF)

O 4NF lida com dependências multivaloradas. Existe uma dependência multivalorada quando um atributo pode ter vários atributos dependentes, e esses atributos dependentes são independentes da chave primária. É bastante complexo, mas vamos explorá-lo mais profundamente usando um exemplo.

O exemplo de biblioteca que usamos ao longo destas explicações não se aplica a esse nível de normalização. Normalmente, a 4NF se aplica a situações em que um único atributo pode ter vários atributos dependentes que não se relacionam diretamente com a chave primária.

Vamos usar outro cenário. Imagine um banco de dados que armazena informações sobre publicações. Vamos considerar uma tabela "Publications" (Publicações) com colunas, título, autor, ano_de_publicação e palavras-chave.

publication_id (PK)

título

autor

publication_year

palavras-chave

1

Para matar um pássaro

Harper Lee

1960

Crescimento, Jurídico

2

O Senhor dos Anéis

J. R. R. Tolkien

1954

Fantasia, épico, aventura

3

Orgulho e Preconceito

Jane Austen

1813

Romance, comentário social

A estrutura da tabela acima está violando o 4NF porque:

  • A coluna de palavras-chave tem uma dependência de vários valores da chave primária publication_id. Isso significa que uma publicação pode ter várias palavras-chave, e essas palavras-chave são independentes do identificador exclusivo da publicação.

A solução?

Você pode criar uma tabela separada.

Tabela Publication_keywords

publication_id (FK)

palavra-chave

1

Entrada na idade adulta

1

Legal

2

Fantasia

2

Épico

2

Aventura

3

Romance

3

Comentário social

A tabela recém-criada (Publication_keywords) estabelece uma relação de muitos para muitos entre a publicação e as palavras-chave. Cada publicação pode ter várias palavras-chave vinculadas por meio de publication_id, que é uma chave estrangeira, e cada palavra-chave pode ser associada a várias publicações.

Com isso, eliminamos com sucesso a dependência multivalorada e obtivemos 4NF.

Quinta Forma Normal (5NF)

5NF é a forma mais complexa de normalização que elimina as dependências de junção. Essa é uma situação em que os dados precisam ser unidos a partir de várias tabelas para responder a uma consulta específica, mesmo quando essas tabelas já estão em 4NF.

Em termos mais simples, o 5NF garante que, ao unir as tabelas, você não poderá obter informações adicionais que ainda não estejam disponíveis nas tabelas separadas.

É menos provável que ocorram dependências de união quando as tabelas já estão normalizadas (em 3NF ou 4NF), daí a dificuldade de criar um exemplo claro e direto para 5NF.

No entanto, vamos dar uma olhada nesse cenário em que o 5NF pode ser relevante:

Imagine um banco de dados universitário com tabelas normalizadas para "Cursos" e "Matrículas".

Tabela de cursos

course_id (PK)

course_name

departamento

101

Introdução à programação

Ciência da Computação

202

Estruturas de dados e algoritmos

Ciência da Computação

301

Desenvolvimento Web I

Ciência da Computação

401

Inteligência Artificial

Ciência da Computação

Tabela de registros

enrollment_id (PK)

student_id (FK)

course_id (FK)

grau

1

12345

101

A

2

12345

202

B

3

56789

301

A-

4

56789

401

B+

Supondo que essas tabelas já estejam em 3NF ou 4NF, pode haver uma dependência de união, dependendo de como os dados são armazenados. Por exemplo, um curso tem um requisito de pré-requisito armazenado na tabela "Cursos" como a coluna "prerequisite_course_id".

À primeira vista, isso pode parecer eficiente. No entanto, considere uma consulta que precise recuperar os cursos matriculados de um aluno e seus respectivos pré-requisitos. Nesse cenário, você precisaria unir as tabelas "Courses" (Cursos) e "Enrollments" (Matrículas) e, em seguida, possivelmente unir a tabela "Courses" (Cursos) para recuperar informações de pré-requisito.

A solução?

Para potencialmente eliminar a dependência de junção e obter 5NF, poderíamos introduzir uma tabela separada de "Pré-requisitos do curso":

Tabela de pré-requisitos do curso

course_id (FK)

prerequisite_course_id (FK)

202

101

301

NULL

401

202

Essa abordagem separa as informações de pré-requisitos e permite a recuperação eficiente dos cursos inscritos e seus pré-requisitos em uma única união entre as tabelas "Enrollments" e "Course_prerequisites".

Observação: Estamos presumindo que um aluno só pode ter um pré-requisito por curso.

O 5NF é um tipo de normalização muito complexo e raro, portanto, como alguém que está iniciando sua jornada de aprendizado em dados, talvez você não encontre uma aplicação. No entanto, será um conhecimento adicional que o deixará preparado quando você se deparar com bancos de dados complexos.

Desenvolva suas habilidades em SQL

Se você está lendo isso, parabéns por ter ficado até o fim. Foi um ótimo passeio explorar o que é normalização em SQL, por que a normalização em SQL é importante, o que causa a necessidade de normalização e os diferentes tipos de normalização de banco de dados. Os cenários usados para explicar os diferentes tipos de normalização servem para que você possa entender completamente e também aplicar esse conhecimento em sua jornada de aprendizado.

A normalização é uma habilidade fundamental para qualquer pessoa que esteja iniciando sua carreira em qualquer caminho profissional relacionado a dados. Ao compreender esses princípios, você está pronto para criar bancos de dados eficientes e bem organizados.

O aprendizado é muito importante no espaço de dados e, para que você aprimore suas habilidades em SQL, temos alguns recursos para você.

Perguntas frequentes

O que é normalização no DBMS?

A normalização de banco de dados é uma técnica que projeta de forma ideal o esquema de um banco de dados relacional. Isso envolve a divisão de tabelas em subtabelas menores e o armazenamento de ponteiros para dados em vez de replicá-los.

Por que a normalização é importante?

A normalização ajuda a evitar a redundância de dados, melhora a integridade dos dados e simplifica a manipulação de dados em um banco de dados.

Preciso normalizar meu banco de dados para 5NF?

Não necessariamente. A normalização 3NF ou 4NF geralmente é suficiente para a maioria dos bancos de dados. O 5NF é a forma mais rigorosa e pode ser útil para bancos de dados complexos com padrões de consulta específicos.

Como posso decidir se preciso normalizar para 5NF?

Analise cuidadosamente suas consultas e o modelo de dados. Se você precisar unir várias tabelas para recuperar informações que podem ser teoricamente derivadas das próprias tabelas separadas, talvez valha a pena considerar o 5NF. No entanto, sempre pese a complexidade em relação aos possíveis ganhos de desempenho. Você pode consultar a seção 5NF, onde um cenário de caso foi usado para obter mais entendimento.

Temas

Continue sua jornada SQL hoje mesmo!

curso

Intermediate SQL

4 hr
280.4K
Accompanied at every step with hands-on practice queries, this course teaches you everything you need to know to analyze data using your own SQL code today!
Ver DetalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado

blog

O que é um banco de dados gráfico? Um guia para iniciantes

Explore o intrincado mundo dos bancos de dados gráficos com nosso guia para iniciantes. Entenda as relações entre os dados, aprofunde-se na comparação entre bancos de dados relacionais e gráficos e explore casos de uso práticos.

Kurtis Pykes

11 min

SQL Programming Language

blog

O que é SQL? - A linguagem essencial para o gerenciamento de bancos de dados

Saiba tudo sobre o SQL e por que ele é a linguagem de consulta ideal para o gerenciamento de bancos de dados relacionais.
Summer Worsley's photo

Summer Worsley

16 min

tutorial

Tutorial de visão geral do banco de dados SQL

Neste tutorial, você aprenderá sobre bancos de dados em SQL.
DataCamp Team's photo

DataCamp Team

3 min

tutorial

SELEÇÃO de várias colunas no SQL

Saiba como selecionar facilmente várias colunas de uma tabela de banco de dados em SQL ou selecionar todas as colunas de uma tabela em uma consulta simples.
DataCamp Team's photo

DataCamp Team

3 min

tutorial

Tutorial do MySQL: Um guia abrangente para iniciantes

Descubra o que é o MySQL e como começar a usar um dos sistemas de gerenciamento de banco de dados mais populares.

tutorial

Como usar um alias SQL para simplificar suas consultas

Explore como o uso de um alias SQL simplifica os nomes de colunas e tabelas. Saiba por que usar um alias SQL é fundamental para melhorar a legibilidade e gerenciar uniões complexas.
Allan Ouko's photo

Allan Ouko

9 min

See MoreSee More