curso
Normalización en SQL (1NF - 5NF): Guía para principiantes
En este artículo exploraremos los conceptos básicos que debes conocer sobre la normalización, su importancia y las distintas técnicas que intervienen. Este artículo va dirigido, aunque no exclusivamente, a quienes buscan introducirse en la industria de los datos.
¿Qué es la Normalización en SQL?
La normalización, en este contexto, es el proceso de organizar los datos dentro de una base de datos(base de datos relacional) para eliminar las anomalías de los datos, como la redundancia.
En términos más sencillos, consiste en descomponer una tabla grande y compleja en tablas más pequeñas y sencillas, manteniendo las relaciones entre los datos.
La normalización se utiliza habitualmente cuando se trabaja con grandes conjuntos de datos.
Veamos brevemente algunos supuestos en los que se suele utilizar la normalización.
Integridad de los datos
Imagina una base de datos que contiene información sobre los clientes. Sin normalización, si un cliente cambia de edad, tendríamos que actualizarla en varios sitios, lo que aumentaría el riesgo de incoherencias. Al normalizar los datos, podemos tener tablas separadas vinculadas por un identificador único que garantizará que los datos sigan siendo precisos y coherentes.
Consulta de eficacia
Consideremos una base de datos compleja con múltiples tablas relacionadas que almacena información redundante. En este escenario, las consultas que implican uniones se vuelven más complicadas y consumen más recursos. La normalización ayudará a simplificar las consultas al dividir los datos en tablas más pequeñas, en las que cada tabla contendrá sólo la información relevante, reduciendo así la necesidad de complejas uniones.
Optimización del almacenamiento
Un problema importante de los datos redundantes es que ocupan espacio de almacenamiento innecesario. Por ejemplo, si almacenamos los mismos detalles del producto en cada registro de pedido, se produce una duplicación. Con la normalización, puedes eliminar la redundancia dividiendo los datos en tablas separadas.
¿Por qué es importante la normalización en SQL?
La normalización desempeña un papel crucial en el diseño de bases de datos. He aquí varias razones por las que es esencial:
- Reduce la redundancia: La redundancia se produce cuando la misma información se almacena varias veces, y una buena forma de evitarla es dividir los datos en tablas más pequeñas.
- Mejora el rendimiento de la consulta: Puedes realizar una ejecución más rápida de las consultas en tablas más pequeñas que hayan sufrido una normalización.
- Minimiza las anomalías de actualización: Con las tablas normalizadas, puedes actualizar fácilmente los datos sin afectar a otros registros.
- Mejora la integridad de los datos: Garantiza que los datos sigan siendo coherentes y precisos.
¿Cuál es la causa de la necesidad de normalización?
Si una tabla no está correctamente normalizada y tiene redundancia de datos, no sólo ocupará espacio extra de almacenamiento de datos, sino que también dificultará el manejo y la actualización de la base de datos.
Hay varios factores que impulsan la necesidad de normalización, desde la redundancia de datos (como se ha explicado anteriormente) hasta la dificultad para gestionar las relaciones. Vayamos al grano:
- Anomalías de inserción, borrado y actualización: Cualquier forma de cambio en una tabla puede provocar errores o incoherencias en otras tablas si no se maneja con cuidado. Estos cambios pueden consistir en añadir nuevos datos a una base de datos, actualizarlos o eliminar registros, lo que puede provocar una pérdida involuntaria de datos.
- Dificultad para gestionar las relaciones: Resulta más difícil mantener relaciones complejas en una estructura no normalizada.
- Otros factores que impulsan la necesidad de normalización son las dependencias par ciales y las dependencias transitivas, en las que las dependencias parciales pueden provocar redundancia de datos y anomalías de actualización, y las dependencias transitivas pueden provocar anomalías de datos. En los próximos apartados veremos cómo tratar estas dependencias para garantizar la normalización de la base de datos.
Diferentes tipos de normalización de bases de datos
Hasta ahora, hemos visto qué es la normalización en SQL, por qué es importante la normalización en SQL y qué causa la necesidad de normalizar. La normalización de las bases de datos adopta distintas formas, cada una con niveles crecientes de organización de los datos.
En esta sección, hablaremos brevemente de los distintos niveles de normalización y luego los exploraremos más a fondo en la sección siguiente.
Imagen del autor
Primera forma normal (1NF)
Este nivel de normalización garantiza que cada columna de tus datos contenga sólo valores atómicos. Valores atómicos en este contexto significa que cada entrada de una columna es indivisible. Es como decir que cada celda de una hoja de cálculo debe contener un solo dato. 1NF garantiza la atomicidad de los datos, ya que cada celda de columna contiene un único valor y cada columna tiene nombres únicos.
Segunda forma normal (2NF)
Elimina las dependencias parciales garantizando que los atributos que no son clave sólo dependan de la clave primaria. Lo que esto significa, en esencia, es que debe haber una relación directa entre cada columna y la clave primaria, y no entre otras columnas.
Tercera forma normal (3NF)
Elimina las dependencias transitivas garantizando que los atributos que no son clave sólo dependan de la clave primaria. Este nivel de normalización se basa en 2NF.
Forma Normal de Boyce-Codd (BCNF)
Se trata de una versión más estricta de 3NF que aborda anomalías adicionales. En este nivel de normalización, cada determinante es una clave candidata.
Cuarta Forma Normal (4NF)
Se trata de un nivel de normalización que se basa en BCNF al tratar las dependencias multivaluadas.
Quinta forma normal (5NF)
5NF es el nivel de normalización más alto que aborda las dependencias de unión. Se utiliza en escenarios específicos para minimizar aún más la redundancia dividiendo una tabla en tablas más pequeñas.
Normalización de bases de datos con ejemplos reales
Ya hemos destacado todos los niveles de normalización de los datos. Vamos a profundizar en cada una de ellas con ejemplos y explicaciones.
Normalización de la Primera Forma Normal (1NF)
1NF garantiza que cada celda de columna contenga sólo valores atómicos. Imagina una base de datos de biblioteca con una tabla que almacena información sobre libros (título, autor, género y prestado_por). Si la tabla no está normalizada, borrowed_by podría contener una lista de nombres de prestatarios separados por comas. Esto viola 1NF, ya que una sola celda contiene varios valores. La tabla siguiente es una buena representación de una tabla que viola 1NF, como se ha descrito anteriormente.
title |
autor |
genre |
borrowed_by |
Matar a un ruiseñor |
Harper Lee |
Ficción |
John Doe, Jane Doe, James Brown |
El Señor de los Anillos |
J. R. R. Tolkien |
Fantasía |
Emily García, David Lee |
Harry Potter y la piedra filosofal |
J.K. Rowling |
Fantasía |
Michael Chen |
¿La solución?
En 1NF, creamos una tabla separada para los prestatarios y la vinculamos a la tabla de libros. Estas tablas pueden vincularse utilizando la clave externa de la tabla de prestatarios o una tabla de vinculación independiente. El enfoque de clave ajena en la tabla prestatarios implica añadir una columna de clave ajena a la tabla prestatarios que haga referencia a la clave primaria de la tabla libros. Esto hará que se establezca una relación entre las tablas, garantizando la coherencia de los datos.
Puedes encontrar una representación de esto a continuación:
Mesa de libros
book_id (PK) |
title |
autor |
genre |
1 |
Matar a un ruiseñor |
Harper Lee |
Ficción |
2 |
El Señor de los Anillos |
J. R. R. Tolkien |
Fantasía |
3 |
Harry Potter y la piedra filosofal |
J.K. Rowling |
Fantasía |
Tabla de prestatarios
borrower_id (PK) |
nombre |
book_id (FK) |
1 |
John Doe |
1 |
2 |
Jane Doe |
1 |
3 |
James Brown |
1 |
4 |
Emily García |
2 |
5 |
David Lee |
2 |
6 |
Michael Chen |
3 |
Segunda forma normal (2NF)
Este nivel de normalización, como ya se ha descrito, se basa en 1NF al garantizar que no existen dependencias parciales de la clave primaria. En términos más sencillos, todos los atributos que no sean clave deben depender de toda la clave primaria y no sólo de una parte de ella.
A partir del 1NF que se implementó, ya tenemos dos tablas separadas (puedes consultar la sección 1NF).
Ahora, supongamos que queremos vincular estas tablas para registrar los préstamos. El planteamiento inicial podría ser simplemente añadir una columna borrower_id a la tabla books, como se muestra a continuación:
book_id (PK) |
title |
autor |
genre |
borrower_id (FK) |
1 |
Matar a un ruiseñor |
Harper Lee |
Ficción |
1 |
2 |
El Señor de los Anillos |
J. R. R. Tolkien |
Fantasía |
NULL |
3 |
Harry Potter y la piedra filosofal |
J.K. Rowling |
Fantasía |
6 |
Esto podría parecer una solución, pero viola 2NF simplemente porque el identificador del prestatario sólo depende parcialmente del identificador del libro. Un libro puede tener varios prestatarios, pero un único borrower_id sólo puede estar vinculado a un libro en esta estructura. Esto crea una dependencia parcial.
¿La solución?
Necesitamos conseguir la relación muchos-a-muchos entre libros y prestatarios para conseguir 2NF. Esto puede hacerse introduciendo una tabla separada:
Tabla empréstitos_contables
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 |
Esta tabla establece una relación clara entre libros y prestatarios. El book_id y el borrower_id actúan como claves externas, haciendo referencia a las claves primarias de sus respectivas tablas. Este enfoque garantiza que borrower_id depende de toda la clave primaria (book_id) de la tabla books, cumpliendo con 2NF.
Tercera forma normal (3NF)
3NF se basa en 2NF eliminando las dependencias transitivas. Una dependencia transitiva se produce cuando un atributo no clave depende de otro atributo no clave, que a su vez depende de la clave primaria. Básicamente toma su significado de la ley transitiva.
A partir de la 2NF que ya hemos implementado, hay tres tablas en la base de datos de nuestra biblioteca:
Mesa de libros
book_id (PK) |
title |
autor |
genre |
1 |
Matar a un ruiseñor |
Harper Lee |
Ficción |
2 |
El Señor de los Anillos |
J. R. R. Tolkien |
Fantasía |
3 |
Harry Potter y la piedra filosofal |
J.K. Rowling |
Fantasía |
Tabla de prestatarios
borrower_id (PK) |
nombre |
book_id (FK) |
1 |
John Doe |
1 |
2 |
Jane Doe |
1 |
3 |
James Brown |
1 |
4 |
Emily García |
2 |
5 |
David Lee |
2 |
6 |
Michael Chen |
3 |
Tabla empréstitos_contables
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 |
La estructura 2NF parece eficiente, pero podría haber una dependencia oculta. Imagina que añadimos una columna fecha_debido a la tabla libros. Esto puede parecer lógico a primera vista, pero va a crear una dependencia transitiva en la que:
- La columna fecha_de_vencimiento depende de borrowing_id (un atributo no clave) de la tabla book_borrowings.
- A su vez, borrowing_id depende de book_id (la clave primaria) de la tabla books.
Esto implica que due_date se basa en un atributo intermedio no clave (borrowing_id) en lugar de depender directamente de la clave primaria (book_id). Esto viola la 3NF.
¿La solución?
Podemos mover la columna fecha_debido a la tabla más adecuada actualizando la tabla préstamos_libros para incluir las columnas fecha_debido y fecha_devuelto.
A continuación se muestra la tabla actualizada:
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 |
Al colocar la columna fecha_de_vencimiento en la tabla préstamo_de_libros, hemos eliminado con éxito la dependencia transitiva.
Esto significa que ahora la fecha de vencimiento depende directamente de la relación combinada entre book_id y borrower_id. En este contexto, book_id y borrower_id actúan como una clave externa compuesta, que juntas forman la clave primaria de la tabla book_borrowings.
Forma Normal de Boyce-Codd (BCNF)
BCNF se basa en dependencias funcionales que consideran todas las claves candidatas de una relación.
Las dependencias funcionales (DF) definen las relaciones entre atributos dentro de una base de datos relacional. Un FD establece que el valor de una columna determina el valor de otra columna relacionada. Los FD son muy importantes porque guían el proceso de normalización identificando las dependencias y garantizando que los datos se distribuyen adecuadamente entre las tablas.
BCNF es una versión más estricta de 3NF. Garantiza que cada determinante (conjunto de atributos que identifican de forma única una fila) de una tabla sea una clave candidata (conjunto mínimo de atributos que identifican de forma única una fila). La esencia de todo esto es que todos los determinantes deben poder servir como claves primarias.
Garantiza que cada dependencia funcional (DF) tenga una superclave como determinante. En otras palabras, si X -> Y (X determina Y) se cumple, X debe ser una clave candidata (superclave) de la relación. Ten en cuenta que X e Y son columnas de una tabla de datos.
A partir de la 3NF, tenemos tres tablas:
Mesa de libros
book_id (PK) |
title |
autor |
genre |
1 |
Matar a un ruiseñor |
Harper Lee |
Ficción |
2 |
El Señor de los Anillos |
J. R. R. Tolkien |
Fantasía |
3 |
Harry Potter y la piedra filosofal |
J.K. Rowling |
Fantasía |
Tabla de prestatarios
borrower_id (PK) |
nombre |
book_id (FK) |
1 |
John Doe |
1 |
2 |
Jane Doe |
1 |
3 |
James Brown |
1 |
4 |
Emily García |
2 |
5 |
David Lee |
2 |
6 |
Michael Chen |
3 |
Tabla empréstitos_contables
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 |
Aunque la estructura 3NF es buena, podría haber un determinante oculto en la tabla préstamos_libros. Suponiendo que un prestatario no pueda tomar prestado el mismo libro dos veces simultáneamente, la combinación de book_id y borrower_id identifica de forma única un registro de préstamo.
Esta estructura viola BCNF, ya que el conjunto combinado (book_id y borrower_id) no es la clave primaria de la tabla (que es sólo borrowing_id).
¿La solución?
Para conseguir la BCNF, podemos descomponer la tabla préstamos_libros en dos tablas separadas o hacer que el conjunto de atributos combinado sea la clave primaria.
- Enfoque 1 (descomponer la tabla): En este enfoque, descompondremos la tabla book_borrowings en tablas separadas:
-
- Una tabla con borrowing_id como clave principal, borrowed_date, due_date y returned_date.
- Otra tabla independiente para vincular libros y prestatarios, con book_id como clave foránea, borrower_id como clave foránea y, potencialmente, atributos adicionales específicos del evento de préstamo.
- Enfoque 2 (hacer que el conjunto de atributos combinados sea la clave primaria): Podemos considerar hacer que book_id y borrower_id sean una clave primaria compuesta para identificar de forma única los registros de préstamo. El problema de este planteamiento es que no servirá a su propósito si un prestatario puede pedir prestado el mismo libro varias veces.
Al final, tu elección entre estas opciones depende de tus necesidades concretas de datos y de cómo quieras modelar las relaciones de préstamo.
Cuarta Forma Normal (4NF)
4NF trata con dependencias multivaluadas. Existe una relación multivaluada cuando un atributo puede tener varios atributos dependientes, y estos atributos dependientes son independientes de la clave primaria. Es bastante complejo, pero vamos a profundizar en él utilizando un ejemplo.
El ejemplo de biblioteca que hemos estado utilizando a lo largo de estas explicaciones no es aplicable a este nivel de normalización. 4NF se aplica normalmente a situaciones en las que un único atributo puede tener varios atributos dependientes que no se relacionan directamente con la clave primaria.
Utilicemos otro escenario. Imagina una base de datos que almacena información sobre publicaciones. Vamos a considerar una tabla "Publicaciones" con las columnas título, autor, año_publicación y palabras clave.
publication_id (PK) |
title |
autor |
publication_year |
palabras clave |
1 |
Matar a un ruiseñor |
Harper Lee |
1960 |
Mayoría de edad, Legal |
2 |
El Señor de los Anillos |
J. R. R. Tolkien |
1954 |
Fantasy, Epic, Adventure |
3 |
Orgullo y prejuicio |
Jane Austen |
1813 |
Romance, Comentario social |
La estructura de tabla anterior infringe 4NF porque:
- La columna keywords tiene una dependencia multivaluada de la clave primaria publication_id. Esto significa que una publicación puede tener varias palabras clave, y que estas palabras clave son independientes del identificador único de la publicación.
¿La solución?
Podemos crear una tabla aparte.
Publication_keywords table
publication_id (FK) |
palabra clave |
1 |
La mayoría de edad |
1 |
Legal |
2 |
Fantasía |
2 |
Épica |
2 |
Aventura |
3 |
Romance |
3 |
Comentario social |
La tabla recién creada (Palabras clave_publicación) establece una relación de muchos a muchos entre la publicación y las palabras clave. Cada publicación puede tener varias palabras clave vinculadas a través de publication_id, que es una clave ajena, y cada palabra clave puede estar asociada a varias publicaciones.
Con esto, hemos eliminado con éxito la dependencia multivaluada y conseguido 4NF.
Quinta forma normal (5NF)
5NF es la forma más compleja de normalización que elimina las dependencias de unión. Se trata de una situación en la que hay que unir datos de varias tablas para responder a una consulta concreta, aunque esas tablas ya estén en 4NF.
En términos más sencillos, 5NF garantiza que al unir las tablas no se pueda obtener información adicional que no estuviera ya disponible en las tablas separadas.
Las dependencias de unión son menos probables cuando las tablas ya están normalizadas (en 3NF o 4NF), de ahí la dificultad de crear un ejemplo claro y directo para 5NF.
Sin embargo, echemos un vistazo a este escenario en el que 5NF podría ser relevante:
Imagina una base de datos universitaria con tablas normalizadas para "Cursos" y "Matrículas".
Tabla de cursos
course_id (PK) |
course_name |
departamento |
101 |
Introducción a la programación |
Informática |
202 |
Estructuras de datos y algoritmos |
Informática |
301 |
Desarrollo web I |
Informática |
401 |
Inteligencia Artificial |
Informática |
Tabla de inscripciones
enrollment_id (PK) |
student_id (FK) |
course_id (FK) |
grado |
1 |
12345 |
101 |
A |
2 |
12345 |
202 |
B |
3 |
56789 |
301 |
A- |
4 |
56789 |
401 |
B+ |
Suponiendo que estas tablas ya estén en 3NF o 4NF, podría existir una dependencia de unión en función de cómo se almacenen los datos. Por ejemplo, un curso tiene un requisito previo almacenado en la tabla "Cursos" como columna "requisito_previo_id_curso".
Esto puede parecer eficiente a primera vista. Sin embargo, considera una consulta que necesita recuperar los cursos matriculados de un alumno y sus respectivos prerrequisitos. En este caso, tendrías que unir las tablas "Cursos" e "Inscripciones" y, a continuación, unir potencialmente la tabla "Cursos" para recuperar la información sobre los requisitos previos.
¿La solución?
Para eliminar potencialmente la dependencia de la unión y conseguir 5NF, podríamos introducir una tabla "Requisitos previos del curso" independiente:
Tabla de requisitos previos del curso
course_id (FK) |
prerequisite_course_id (FK) |
202 |
101 |
301 |
NULL |
401 |
202 |
Este enfoque separa la información de los prerrequisitos y permite una recuperación eficaz de los cursos matriculados y sus prerrequisitos en una única unión entre las tablas "Matriculaciones" y "Prerrequisitos_curso".
Nota: Suponemos que un estudiante sólo puede tener un prerrequisito por curso.
5NF es un tipo de normalización muy complejo y poco frecuente, por lo que, como persona que acaba de iniciar su andadura de aprendizaje en datos, puede que no encuentres una aplicación. Sin embargo, será un conocimiento añadido y te hará estar preparado cuando tropieces con bases de datos complejas.
Desarrolla tus habilidades SQL
Si estás leyendo esto, enhorabuena por haberte quedado hasta el final. Ha sido un gran viaje explorando qué es la normalización en SQL, por qué es importante la normalización en SQL, qué causa la necesidad de normalización y los distintos tipos de normalización de bases de datos. Los escenarios utilizados en la explicación de los distintos tipos de normalización son para que puedas comprenderlos plenamente y también para que puedas aplicar estos conocimientos en tu viaje de aprendizaje.
La normalización es una habilidad fundamental para cualquiera que se inicie en cualquier carrera relacionada con los datos. Al comprender estos principios, ya estás preparado para crear bases de datos eficaces y bien organizadas.
El aprendizaje es muy importante en el espacio de los datos, y para que mejores tus conocimientos de SQL, tenemos algunos recursos para ti.
Preguntas frecuentes
¿Qué es la normalización en un SGBD?
La normalización de bases de datos es una técnica que diseña de forma óptima el esquema de una base de datos relacional. Consiste en dividir las tablas en subtablas más pequeñas y almacenar punteros a los datos en lugar de replicarlos.
¿Por qué es importante la normalización?
La normalización ayuda a evitar la redundancia de datos, mejora su integridad y simplifica su manipulación dentro de una base de datos.
¿Necesito normalizar mi base de datos a 5NF?
No necesariamente. La normalización 3NF o 4NF suele ser suficiente para la mayoría de las bases de datos. 5NF es la forma más rigurosa y podría ser beneficiosa para bases de datos complejas con patrones de consulta específicos.
¿Cómo puedo decidir si necesito normalizar a 5NF?
Analiza cuidadosamente tus consultas y tu modelo de datos. Si necesitas unir varias tablas para recuperar información que teóricamente podría derivarse de las tablas separadas, puede que merezca la pena plantearse el 5NF. Sin embargo, sopesa siempre la complejidad frente a las posibles ganancias de rendimiento. Puedes consultar la sección 5NF, donde se utilizó un supuesto práctico para comprenderlo mejor.
¡Continúa hoy tu viaje SQL!
curso
Joining Data in SQL
curso
Exploratory Data Analysis in SQL
blog
¿Qué es una base de datos de grafos? Guía para principiantes
blog
5 competencias esenciales en ingeniería de datos
tutorial
Cómo utilizar un alias SQL para simplificar tus consultas

Allan Ouko
9 min
tutorial
Seleccionar varias columnas en SQL

DataCamp Team
3 min
tutorial
Ejemplos y tutoriales de consultas SQL
tutorial
Base de datos Azure SQL: Configuración y gestión paso a paso

Anneleen Rummens
25 min