Hello! Welcome to your first lesson on database design.
In our last session, we explored how to write complex queries using JOINs and subqueries to pull data from multiple tables. This is a crucial skill for retrieving information. But it raises a fundamental question: why is data split across multiple tables in the first place? Why not just have one massive table for everything?
This lesson answers that question. We will dive into the principles of good database design. You will learn how to define functional dependencies and normalize a database to First Normal Form (1NF). This is the first step in a process called normalization, which is a systematic way to organize your database to prevent common problems and ensure your data is reliable and easy to manage. Understanding these concepts is fundamental for the GATE exam and for building any robust data-driven application.
The Problem: Why a Single Large Table is a Bad Idea
Imagine we're building a database for a university and decide to store all student and course information in a single table. It might look something like this:
| student_id | student_name | course_id | course_name | instructor_name |
|---|---|---|---|---|
| S1 | Anjali | C101 | Intro to Python | Dr. Sharma |
| S2 | Ben | C101 | Intro to Python | Dr. Sharma |
| S2 | Ben | C102 | Data Structures | Dr. Gupta |
| S3 | Priya | C102 | Data Structures | Dr. Gupta |
At first glance, this seems simple. But this design suffers from serious issues:
- Data Redundancy: Notice how the information for "C101, Intro to Python, Dr. Sharma" is repeated for every student enrolled in that course. This wastes space and, more importantly, creates opportunities for errors.
- Anomalies: This redundancy leads to problems when you try to insert, update, or delete data. These problems are called anomalies.
To understand these anomalies better, let's watch a short video that explains them with a clear example.
Lec-20: Introduction to Normalization | Insertion, Deletion & Updation Anomaly
This video from Gate Smashers clearly demonstrates the three main types of anomalies—insertion, deletion, and updation—that arise from a poorly designed database table.
Please watch from 02:01 to 11:09. As you watch, focus on understanding: Insertion Anomaly (04:02): Why can't we add a new course if no student is enrolled in it yet? Deletion Anomaly (05:57): What happens to the course information if the only student enrolled in it drops out? Updation Anomaly (07:53): If an instructor's salary changes, why is it inefficient and risky to update this information in our table?
As you can see, these anomalies make our database unreliable. The solution is normalization: a process of breaking down large, problematic tables into smaller, well-structured ones. The first step in normalization is to understand the relationships between the data, which we do using functional dependencies.
Functional Dependencies: The Rules of Your Data
A functional dependency is a constraint or a rule that describes the relationship between attributes (columns) in a table.
We say that an attribute B is functionally dependent on an attribute A if, for any given value of A, we can uniquely determine the value of B. We write this as:
A → B ("A determines B")
The formal rule is:
In a table, for any two rows, if the values in column
Aare the same, then the values in columnBmust also be the same.
Let's look at our example table again:
| student_id | student_name | course_id | course_name | instructor_name |
|---|---|---|---|---|
| S1 | Anjali | C101 | Intro to Python | Dr. Sharma |
| S2 | Ben | C101 | Intro to Python | Dr. Sharma |
| S2 | Ben | C102 | Data Structures | Dr. Gupta |
| S3 | Priya | C102 | Data Structures | Dr. Gupta |
Here are some functional dependencies:
student_id → student_name: For anystudent_id(e.g., 'S2'), thestudent_name('Ben') is always the same. This is a valid FD.course_id → course_name: For anycourse_id(e.g., 'C101'), thecourse_name('Intro to Python') is always the same. This is a valid FD.student_name → student_id: Is this valid? What if two students are named 'Ben'? We couldn't uniquely determine their ID. So,student_namedoes not determinestudent_id. This is an invalid FD.
The following video provides a great introduction to this concept, using an analogy to mathematical functions that should be familiar to you.
This video from 'making IT simple' explains the core concept of functional dependencies and walks through several examples to test your understanding of what makes a dependency valid or invalid.
Watch the video from the beginning to 07:19. Pay close attention to the four cases the presenter discusses to determine if a functional dependency holds true.
Functional dependencies are the building blocks of database normalization. By identifying all the FDs in a table, we can understand its structure and figure out how to break it down correctly.

Test your understanding!
Consider a table Products with columns ProductID, ProductName, CategoryID, and CategoryName.
Which of the following functional dependencies are most likely to be true?
ProductID → ProductNameProductName → ProductIDCategoryName → CategoryIDProductID → CategoryName
Show answer
The most likely true functional dependencies are:
ProductID → ProductName: Each unique product ID should correspond to exactly one product name.ProductID → CategoryName: Each unique product ID belongs to a specific category, so its category name should be determined.
The other two are less likely:
ProductName → ProductID: It's possible for different products (e.g., a phone and a phone case) to have similar or even identical names but different IDs.CategoryName → CategoryID: While often true, it's safer to assume the ID determines the name, not the other way around, in case of naming changes or similar category names.
For a more formal and structured definition, which is useful for exam preparation, you can refer to the following resource.
This article from GateVidyalay provides a concise, formal definition of functional dependency and also introduces trivial vs. non-trivial dependencies.
Read the sections 'Functional Dependency-' and 'Types Of Functional Dependencies-'. Don't worry about the 'Inference Rules' for now; we'll touch on those later.
First Normal Form (1NF): Ensuring Atomicity
Now that we understand anomalies and functional dependencies, we can begin normalizing. The first step is achieving the First Normal Form (1NF).
A table is in 1NF if it satisfies a few basic rules, but the most important one is:
Every attribute (column) must hold only atomic (indivisible) values.
This means you cannot have multiple values stuffed into a single cell. For example, a phone_numbers column cannot contain '12345, 67890'.
Let's look at a table that is not in 1NF:
| emp_id | emp_name | emp_skills |
|---|---|---|
| 1 | John | Python, JavaScript |
| 2 | Darth | HTML, CSS, JavaScript |
The emp_skills column violates 1NF because it contains multiple, comma-separated values. To fix this and bring the table into 1NF, we have two main options.
The following reading explains these rules and conversion methods very clearly.
This article from StudyTonight introduces normalization and then provides a detailed explanation of First Normal Form (1NF) with a clear example.
Please read the following sections: Start with 'Normalization in DBMS' and 'Problems without Normalization in DBMS' for a good recap of the 'why'. Then, jump to the section '1. First Normal Form (1NF)'. Pay close attention to the two methods shown to convert the non-1NF table into 1NF. This is a crucial concept.
As the article shows, the two ways to achieve 1NF are:
-
Expanding the Table: Repeat the employee information for each skill. This makes the table 1NF but creates a lot of redundancy (e.g., John's
emp_idandemp_nameare repeated).emp_id emp_name emp_skill 1 John Python 1 John JavaScript 2 Darth HTML 2 Darth CSS 2 Darth JavaScript -
Decomposition: Break the original table into two separate tables: one for employees and one for skills, linked by
emp_id. This is the preferred approach.Employee Table:
emp_id emp_name 1 John 2 Darth Employee_Skill Table:
emp_id emp_skill 1 Python 1 JavaScript 2 HTML 2 CSS 2 JavaScript
Decomposition is the essence of normalization. By achieving 1NF, we have solved the problem of multi-valued attributes and have taken the first step toward a clean, robust database design.
Conclusion
In this lesson, we've laid the groundwork for good database design. You learned why stuffing all your data into one large table is a bad idea and how it leads to data redundancy and update anomalies.
Key Takeaways:
- Poorly designed tables suffer from insertion, deletion, and updation anomalies, making them unreliable.
- Functional Dependencies (FDs) are rules (
A → B) that formally describe how attributes in a table relate to each other. Identifying them is key to normalization. - Normalization is the process of decomposing tables to reduce redundancy and eliminate anomalies.
- First Normal Form (1NF) is the first step, requiring that all table columns contain only atomic (single) values.
Preview of the Next Lesson:
Achieving 1NF is essential, but it doesn't solve all our problems. As you saw in the "expanding the table" method, a 1NF table can still have significant data redundancy. In our next lesson, "Normalize a database schema to Second (2NF) and Third Normal Form (3NF)," we will learn how to use functional dependencies to identify and eliminate these more subtle forms of redundancy, bringing us much closer to a truly well-designed database.