@Codingdidi
9.45K subscribers
26 photos
7 videos
47 files
257 links
Free learning Resources For Data Analysts, Data science, ML, AI, GEN AI and Job updates, career growth, Tech updates
Download Telegram
πŸ“Œ Summary Table: SQL Set Operators
| Operator | Description | Removes Duplicates? |
|-----------|------------|---------------------|
| UNION | Combines results from two queries | βœ… Yes |
| UNION ALL | Combines results, including duplicates | ❌ No |
| INTERSECT | Returns only common records | βœ… Yes |
| EXCEPT | Returns records in the first query but not in the second | βœ… Yes |

---

πŸ“Œ Real-Life Use Cases of Set Operators

πŸ”Ή Merging Employee Data
Find all employees from multiple company branches without duplicates.
SELECT EmployeeID, Name FROM BranchA  
UNION
SELECT EmployeeID, Name FROM BranchB;


πŸ”Ή Finding Common Customers
Identify customers who bought from both Amazon and Flipkart.
SELECT CustomerID FROM AmazonOrders  
INTERSECT
SELECT CustomerID FROM FlipkartOrders;


πŸ”Ή Detecting Unused Emails
Find email addresses in the registration list that haven’t been used to place an order.
SELECT Email FROM Registrations  
EXCEPT
SELECT Email FROM Orders;


---

πŸ“Œ Your Tasks for Today
βœ… Try out the queries on your SQL editor.
βœ… Comment "Done βœ…" once you complete today’s practice!

Tomorrow, we will explore Views and Indexes in SQL!

πŸ‘‰ Like ❀️ and Share if you're excited for Day 15! 😊
❀4πŸ‘1
Day 15: Common Table Expressions (CTEs) – WITH Clause and Recursive Queries

Welcome to Day 15 of your SQL learning journey! πŸš€ Today, we will dive into Common Table Expressions (CTEs), an advanced SQL concept that makes queries easier to read and write.

πŸ“Œ What is a CTE?
A Common Table Expression (CTE) is a temporary result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE statement.

βœ… CTEs make complex queries simpler and more readable
βœ… They help break down large queries into smaller parts
βœ… CTEs are similar to temporary tables but exist only during query execution

---

πŸ”Ή 1. The WITH Clause – Creating a Simple CTE
The WITH clause is used to define a Common Table Expression (CTE).

πŸš€ Basic Syntax of CTE
WITH CTE_Name AS (
SELECT column1, column2
FROM table_name
WHERE condition
)
SELECT * FROM CTE_Name;

- WITH CTE_Name AS (...) – Creates a temporary result set (CTE).
- The SELECT * FROM CTE_Name statement retrieves data from the CTE.

πŸ” Example: Using CTE to Simplify Queries
Imagine we have a Sales table:

| OrderID | Customer | Amount | OrderDate |
|---------|---------|--------|------------|
| 1 | Alice | 500 | 2024-01-05 |
| 2 | Bob | 700 | 2024-02-10 |
| 3 | Charlie | 300 | 2024-02-15 |
| 4 | Alice | 800 | 2024-03-01 |

We want to find customers who spent more than $600 in total.

Instead of writing a complex query, we use a CTE:
WITH TotalSales AS (
SELECT Customer, SUM(Amount) AS TotalAmount
FROM Sales
GROUP BY Customer
)
SELECT Customer, TotalAmount
FROM TotalSales
WHERE TotalAmount > 600;

βœ… Output:
| Customer | TotalAmount |
|---------|------------|
| Alice | 1300 |
| Bob | 700 |

πŸ” How It Works?
- The CTE TotalSales calculates the total spending per customer.
- The final query filters customers with TotalAmount > 600.
- Without a CTE, this would require a nested subquery, making it harder to read!

---

πŸ”Ή 2. Recursive CTEs – Handling Hierarchical Data
A recursive CTE is a special type of CTE that refers to itself. It is useful for handling hierarchical data like:
βœ… Employee-Manager relationships
βœ… Category-Subcategory structures
βœ… Family trees

πŸš€ Example: Employee Hierarchy
Imagine a CompanyEmployees table:

| EmployeeID | Name | ManagerID |
|-----------|--------|----------|
| 1 | CEO | NULL |
| 2 | Alice | 1 |
| 3 | Bob | 1 |
| 4 | Charlie | 2 |
| 5 | David | 2 |

Here, the CEO (EmployeeID 1) manages Alice and Bob, while Alice manages Charlie and David.

πŸ” Recursive CTE to Find Employee Hierarchy
WITH EmployeeHierarchy AS (
-- Base Case: Select the CEO (Top-level manager)
SELECT EmployeeID, Name, ManagerID, 1 AS Level
FROM CompanyEmployees
WHERE ManagerID IS NULL

UNION ALL

-- Recursive Case: Select employees and increase hierarchy level
SELECT e.EmployeeID, e.Name, e.ManagerID, h.Level + 1
FROM CompanyEmployees e
INNER JOIN EmployeeHierarchy h
ON e.ManagerID = h.EmployeeID
)
SELECT * FROM EmployeeHierarchy;

βœ… Output:
| EmployeeID | Name | ManagerID | Level |
|-----------|--------|----------|------|
| 1 | CEO | NULL | 1 |
| 2 | Alice | 1 | 2 |
| 3 | Bob | 1 | 2 |
| 4 | Charlie | 2 | 3 |
| 5 | David | 2 | 3 |

πŸ” How It Works?
1️⃣ Base Case: The CEO (ManagerID NULL) starts at Level 1.
2️⃣ Recursive Case: Employees reporting to the CEO are Level 2.
3️⃣ Recursion continues until all employee levels are calculated.

---

πŸ“Œ When to Use CTEs?
βœ… When you need to simplify complex queries
βœ… When working with hierarchical data (Employee-Manager, Categories, etc.)
βœ… When breaking large queries into readable parts
βœ… When avoiding repetitive subqueries

---
πŸ“Œ Summary Table: CTE vs. Subquery vs. Temporary Table
| Feature | CTE (WITH) | Subquery | Temporary Table |
|----------|-------------|----------|----------------|
| Exists Temporarily? | βœ… Yes | ❌ No | ❌ No |
| Improves Readability? | βœ… Yes | ❌ No | βœ… Yes |
| Supports Recursion? | βœ… Yes | ❌ No | ❌ No |
| Requires Explicit Deletion? | ❌ No | ❌ No | βœ… Yes |

---

πŸ“Œ Your Tasks for Today
βœ… Try out the queries in your SQL editor
βœ… Practice a recursive CTE with your own dataset
βœ… Comment "Done βœ…" once you complete today’s practice!

Tomorrow, we will explore Indexes and Performance Optimization in SQL!

πŸ‘‰ Like ❀️ and Share if you're excited for Day 16! 😊
❀2
Day 16: Window Functions – ROW_NUMBER, RANK, DENSE_RANK, NTILE

Welcome to Day 16 of your SQL learning journey! πŸš€ Today, we will explore Window Functions, which help perform calculations across a specific group of rows without collapsing them into a single value.

πŸ“Œ What are Window Functions?
A Window Function allows us to perform calculations over a subset of rows while keeping all original rows in the result.

βœ… They do not group the data like `GROUP BY`
βœ… They provide ranking, numbering, and distribution calculations
βœ… Each row retains its identity while calculations are performed on a subset of data

---

πŸ”Ή 1. Understanding the OVER() Clause
All window functions work using the OVER() clause, which defines how the calculation is applied.

πŸš€ Basic Syntax of a Window Function
SELECT column_name, 
window_function() OVER (PARTITION BY column_name ORDER BY column_name)
FROM table_name;

- window_function() – The function you want to apply (ROW_NUMBER(), RANK(), etc.).
- OVER() – Defines how the function operates.
- PARTITION BY column_name – Groups data into partitions (optional).
- ORDER BY column_name – Specifies row order for ranking or numbering.

---

πŸ”Ή 2. ROW_NUMBER() – Assigning Unique Row Numbers
The ROW_NUMBER() function assigns a unique number to each row within a partition, starting from 1.

πŸ” Example: Assigning Row Numbers
Imagine we have a Students table:

| StudentID | Name | Subject | Marks |
|-----------|------|---------|-------|
| 1 | Alice | Math | 90 |
| 2 | Bob | Math | 85 |
| 3 | Charlie | Math | 85 |
| 4 | Alice | Science | 88 |
| 5 | Bob | Science | 92 |

We want to assign a row number to each student per subject based on marks.

SELECT Name, Subject, Marks,
ROW_NUMBER() OVER (PARTITION BY Subject ORDER BY Marks DESC) AS RowNum
FROM Students;


βœ… Output:
| Name | Subject | Marks | RowNum |
|---------|---------|-------|--------|
| Alice | Math | 90 | 1 |
| Bob | Math | 85 | 2 |
| Charlie | Math | 85 | 3 |
| Bob | Science | 92 | 1 |
| Alice | Science | 88 | 2 |

πŸ” How It Works?
- `PARTITION BY Subject` β†’ Groups rows by subject.
- `ORDER BY Marks DESC` β†’ Orders students by highest marks.
- Each student gets a unique row number for their subject.

---

πŸ”Ή 3. RANK() – Assigning Rank with Gaps
The RANK() function assigns ranks to rows, but it allows gaps if two rows have the same value.

πŸ” Example: Assigning Ranks with Gaps
SELECT Name, Subject, Marks,
RANK() OVER (PARTITION BY Subject ORDER BY Marks DESC) AS RankNum
FROM Students;


βœ… Output:
| Name | Subject | Marks | RankNum |
|---------|---------|-------|--------|
| Alice | Math | 90 | 1 |
| Bob | Math | 85 | 2 |
| Charlie | Math | 85 | 2 |
| Bob | Science | 92 | 1 |
| Alice | Science | 88 | 2 |

πŸ” How It Works?
- `Bob` and `Charlie` have the same marks (85), so they get the same rank (2).
- Since ranks are skipped (`2 β†’ 4` instead of `2 β†’ 3`), gaps appear in the ranking.

---

πŸ”Ή 4. DENSE_RANK() – Assigning Rank Without Gaps
The DENSE_RANK() function is similar to RANK(), but it does not leave gaps in the ranking.

πŸ” Example: Assigning Dense Ranks
SELECT Name, Subject, Marks,
DENSE_RANK() OVER (PARTITION BY Subject ORDER BY Marks DESC) AS DenseRankNum
FROM Students;


βœ… Output:
| Name | Subject | Marks | DenseRankNum |
|---------|---------|-------|-------------|
| Alice | Math | 90 | 1 |
| Bob | Math | 85 | 2 |
| Charlie | Math | 85 | 2 |
| Bob | Science | 92 | 1 |
| Alice | Science | 88 | 2 |

πŸ” How It Works?
- Like `RANK()`, `Bob` and `Charlie` get the same rank (2).
- Unlike `RANK()`, the next rank continues (no gaps).

---

πŸ”Ή 5. NTILE(N) – Dividing Rows into Equal Groups
The NTILE(N) function divides rows into N equal groups.
πŸ‘1
πŸ” Example: Dividing Students into 2 Groups (NTILE(2))
SELECT Name, Subject, Marks,
NTILE(2) OVER (PARTITION BY Subject ORDER BY Marks DESC) AS TileNum
FROM Students;


βœ… Output:
| Name | Subject | Marks | TileNum |
|---------|---------|-------|--------|
| Alice | Math | 90 | 1 |
| Bob | Math | 85 | 1 |
| Charlie | Math | 85 | 2 |
| Bob | Science | 92 | 1 |
| Alice | Science | 88 | 2 |

πŸ” How It Works?
- Rows are divided into 2 equal groups (`NTILE(2)`).
- If the number of rows isn't perfectly divisible, some groups may have one extra row.

---

πŸ“Œ Summary of Window Functions
| Function | Purpose | Handles Ties? | Gaps in Ranking? |
|--------------|--------------------------------|-------------|---------------|
| ROW_NUMBER() | Assigns unique row numbers | ❌ No | ❌ No |
| RANK() | Assigns ranks with gaps | βœ… Yes | βœ… Yes |
| DENSE_RANK() | Assigns ranks without gaps | βœ… Yes | ❌ No |
| NTILE(N) | Divides rows into N groups | ❌ No | ❌ No |

---

πŸ“Œ When to Use Window Functions?
βœ… When you need row numbers or rankings without grouping data.
βœ… When working with ranked results like leaderboards.
βœ… When dividing data into equal groups using NTILE().

---

πŸ“Œ Your Tasks for Today
βœ… Try out the queries in your SQL editor
βœ… Experiment with `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, and `NTILE(4)`
βœ… Comment "Done βœ…" once you complete today’s practice!

Tomorrow, we will explore Aggregate Functions in SQL!

πŸ‘‰ Like ❀️ and Share if you're excited for Day 17! 😊
Day 17: More Window Functions – LEAD, LAG, FIRST_VALUE, LAST_VALUE

Welcome to Day 17 of your SQL learning journey! πŸš€ Today, we will explore advanced Window Functions, including LEAD, LAG, FIRST_VALUE, and LAST_VALUE. These functions help us compare rows within a partition by looking at previous and next values in a dataset.

πŸ“Œ What are Window Functions?
Window functions perform calculations over a specific group of rows, similar to aggregate functions (SUM, AVG, etc.), but they do not collapse rows into a single output. Instead, they return results for each row individually while considering values from other rows.

---

πŸ”Ή 1. LEAD() – Get the Next Row’s Value
The LEAD() function fetches the value from the next row within the same partition. It is useful for comparing current and next row values.

πŸ” Example: Finding Next Month’s Sales
Imagine we have a Sales table:

| Month | Sales |
|--------|-------|
| Jan | 1000 |
| Feb | 1200 |
| Mar | 1500 |
| Apr | 1300 |

We want to compare this month’s sales with next month’s sales.

SELECT Month, Sales, 
LEAD(Sales) OVER (ORDER BY Month) AS Next_Month_Sales
FROM Sales;


βœ… Output:
| Month | Sales | Next_Month_Sales |
|-------|-------|------------------|
| Jan | 1000 | 1200 |
| Feb | 1200 | 1500 |
| Mar | 1500 | 1300 |
| Apr | 1300 | NULL |

πŸ” How It Works?
- LEAD(Sales) OVER (ORDER BY Month) β†’ Looks at the next row’s sales value.
- April has NULL because there is no next row.

βœ… Use Cases:
- Comparing sales of the current and next month.
- Finding future trends in data.

---

πŸ”Ή 2. LAG() – Get the Previous Row’s Value
The LAG() function fetches the value from the previous row within the same partition. It helps in comparing a current row with its previous row.

πŸ” Example: Comparing Current Sales with Previous Month
SELECT Month, Sales, 
LAG(Sales) OVER (ORDER BY Month) AS Prev_Month_Sales
FROM Sales;


βœ… Output:
| Month | Sales | Prev_Month_Sales |
|-------|-------|------------------|
| Jan | 1000 | NULL |
| Feb | 1200 | 1000 |
| Mar | 1500 | 1200 |
| Apr | 1300 | 1500 |

πŸ” How It Works?
- LAG(Sales) OVER (ORDER BY Month) β†’ Looks at the previous row’s sales value.
- January has NULL because there is no previous row.

βœ… Use Cases:
- Comparing current and past values in sales, stock prices, etc.
- Analyzing month-over-month or year-over-year changes.

---

πŸ”Ή 3. FIRST_VALUE() – Get the First Row’s Value
The FIRST_VALUE() function returns the first value in a partition. It is useful when you need to reference the earliest or starting value.

πŸ” Example: Finding the First Month’s Sales
SELECT Month, Sales, 
FIRST_VALUE(Sales) OVER (ORDER BY Month) AS First_Month_Sales
FROM Sales;


βœ… Output:
| Month | Sales | First_Month_Sales |
|-------|-------|------------------|
| Jan | 1000 | 1000 |
| Feb | 1200 | 1000 |
| Mar | 1500 | 1000 |
| Apr | 1300 | 1000 |

πŸ” How It Works?
- FIRST_VALUE(Sales) OVER (ORDER BY Month) β†’ Returns the first row’s sales value (1000) for every row.

βœ… Use Cases:
- Finding the initial value for a dataset.
- Comparing each row to the starting value.

---

πŸ”Ή 4. LAST_VALUE() – Get the Last Row’s Value
The LAST_VALUE() function returns the last value in a partition. It helps in identifying the latest value in an ordered dataset.

πŸ” Example: Finding the Latest Month’s Sales
SELECT Month, Sales, 
LAST_VALUE(Sales) OVER (ORDER BY Month ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS Last_Month_Sales
FROM Sales;


βœ… Output:
| Month | Sales | Last_Month_Sales |
|-------|-------|-----------------|
| Jan | 1000 | 1300 |
| Feb | 1200 | 1300 |
| Mar | 1500 | 1300 |
| Apr | 1300 | 1300 |
πŸ‘1
πŸ” How It Works?
- LAST_VALUE(Sales) OVER (...) β†’ Looks at the last row’s sales value (1300).
- ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ensures it considers all rows.

βœ… Use Cases:
- Finding the latest recorded value.
- Comparing current values to the last recorded value.

---

πŸ“Œ Summary of Window Functions
| Function | Purpose | Example Use |
|--------------|---------------------------------|----------------------------|
| LEAD() | Get the next row’s value | Comparing current vs next row |
| LAG() | Get the previous row’s value | Comparing current vs previous row |
| FIRST_VALUE() | Get the first row’s value | Finding the starting value |
| LAST_VALUE() | Get the last row’s value | Finding the latest value |

---

πŸ“Œ When to Use These Functions?
βœ… When comparing current and previous row values (LAG()).
βœ… When comparing current and next row values (LEAD()).
βœ… When finding the first value in a dataset (FIRST_VALUE()).
βœ… When finding the latest value in a dataset (LAST_VALUE()).

---

πŸ“Œ Your Tasks for Today
βœ… Try out the queries in your SQL editor.
βœ… Experiment with `LEAD()`, `LAG()`, `FIRST_VALUE()`, and `LAST_VALUE()`.
βœ… Comment "Done βœ…" once you complete today’s practice!

Tomorrow, we will explore Advanced Joins in SQL!

πŸ‘‰ Like ❀️ and Share if you're excited for Day 18! 😊
πŸ‘1
I hope you all are finding this series interesting and helpful at the same time.

IF there's anything that you guys want to add, do let me know.

Happy Learning!!
# Day 18: Creating and Managing Views, Temporary Tables, and Table Variables

Welcome to Day 18 of your SQL learning journey! πŸš€ Today, we will explore:
βœ”οΈ Views – A way to store queries as virtual tables.
βœ”οΈ Temporary Tables – Short-term tables used for temporary data storage.
βœ”οΈ Table Variables – Variables that store table-like structures in memory.

Each of these concepts helps us organize data, improve query performance, and manage temporary results efficiently. Let’s dive in!

---

πŸ”Ή 1. What is a VIEW in SQL?

A VIEW is a virtual table created from a SQL query. It does not store actual data but fetches it from the original table(s) whenever queried.

πŸ“Œ Why Use Views?
βœ… Simplifies Complex Queries – You can save a query as a view and reuse it.
βœ… Security – You can restrict access by exposing only necessary columns.
βœ… Consistency – Ensures that all users work with the same data representation.

---

πŸ” Example: Creating a VIEW
Let’s say we have a table called Employees:

| EmployeeID | Name | Department | Salary |
|-----------|------|------------|--------|
| 1 | John | HR | 50000 |
| 2 | Alice | IT | 70000 |
| 3 | Bob | Finance | 60000 |

Now, we create a VIEW that shows only IT department employees:

CREATE VIEW IT_Employees AS
SELECT EmployeeID, Name, Salary
FROM Employees
WHERE Department = 'IT';


βœ… Now, instead of writing the same query again, we can just run:
SELECT * FROM IT_Employees;

Output:

| EmployeeID | Name | Salary |
|-----------|------|--------|
| 2 | Alice | 70000 |

πŸ“Œ Managing Views
βœ”οΈ Updating a View:
ALTER VIEW IT_Employees AS
SELECT EmployeeID, Name, Salary, Department
FROM Employees
WHERE Department = 'IT';

βœ”οΈ Deleting a View:
DROP VIEW IT_Employees;

βœ”οΈ Updating Data in a View:
- If the view is based on a single table, you can update data directly:
UPDATE IT_Employees 
SET Salary = 75000
WHERE EmployeeID = 2;

- If the view is based on multiple tables, updating may not be allowed.

---

πŸ”Ή 2. What are Temporary Tables in SQL?

A Temporary Table is a table that exists only for the duration of a session. Once the session ends, the table is automatically deleted.

πŸ“Œ Why Use Temporary Tables?
βœ… Store Intermediate Data – Useful when working with complex calculations or large datasets.
βœ… Improve Performance – Speeds up queries by reducing redundant computations.
βœ… Prevents Changes to Main Tables – Temporary tables do not affect original data.

---

πŸ” Example: Creating a Temporary Table
A temporary table name starts with `#`.

CREATE TABLE #TempEmployees (
EmployeeID INT,
Name VARCHAR(50),
Salary DECIMAL(10,2)
);

Now, we insert some values:

INSERT INTO #TempEmployees (EmployeeID, Name, Salary) 
VALUES (1, 'John', 50000),
(2, 'Alice', 70000);


βœ… Fetching Data from Temporary Table
SELECT * FROM #TempEmployees;

Output:

| EmployeeID | Name | Salary |
|-----------|------|--------|
| 1 | John | 50000 |
| 2 | Alice | 70000 |

βœ… Deleting a Temporary Table
DROP TABLE #TempEmployees;

πŸ’‘ Note: Temporary tables are deleted automatically once the session ends!

---

πŸ”Ή 3. What are Table Variables?

A Table Variable is a special type of variable in SQL that holds table-like data. Unlike temporary tables, table variables do not persist beyond the batch execution.

πŸ“Œ Why Use Table Variables?
βœ… Uses Less System Resources – Stored in memory, making operations faster.
βœ… Does Not Require Explicit Deletion – Automatically removed after execution.
βœ… Better for Small Datasets – Works best when dealing with a few rows of data.

---

πŸ” Example: Creating a Table Variable
DECLARE @EmpTable TABLE (
EmployeeID INT,
Name VARCHAR(50),
Salary DECIMAL(10,2)
);


βœ… Inserting Data
INSERT INTO @EmpTable (EmployeeID, Name, Salary) 
VALUES (1, 'John', 50000),
(2, 'Alice', 70000);


βœ… Fetching Data from a Table Variable
SELECT * FROM @EmpTable;


Output:
πŸ‘1
| EmployeeID | Name | Salary |
|-----------|------|--------|
| 1 | John | 50000 |
| 2 | Alice | 70000 |

πŸ’‘ Difference from Temporary Tables:
- Table Variables are limited to the batch they are declared in.
- Table Variables cannot be dropped, they disappear automatically.

---

πŸ“Œ Summary: Views vs. Temporary Tables vs. Table Variables

| Feature | Views | Temporary Tables | Table Variables |
|----------------|-----------------|-----------------|----------------|
| Stores Data? | ❌ (Virtual Table) | βœ… Yes (Temporary) | βœ… Yes (In Memory) |
| Persists? | βœ… Yes (Until Dropped) | ❌ No (Deleted when session ends) | ❌ No (Deleted after batch ends) |
| Performance | πŸ”Ή Faster (No Data Stored) | πŸ”Ή Good for Large Data | πŸ”Ή Best for Small Data |
| Used For? | Read-Only Queries | Storing Intermediate Data | Storing Small Data Temporarily |

---

πŸ“Œ When to Use These Features?
βœ… Use VIEWS to simplify complex queries and improve security.
βœ… Use TEMPORARY TABLES for storing large intermediate results.
βœ… Use TABLE VARIABLES for storing small datasets within a session.

---

πŸ“Œ Your Tasks for Today
βœ… Create a VIEW and query it
βœ… Experiment with TEMPORARY TABLES
βœ… Practice using TABLE VARIABLES

Tomorrow, we will explore Stored Procedures and Functions in SQL!

πŸ‘‰ Like ❀️ and Share if you're excited for Day 19! 😊
πŸ‘2
Day 19: Transactions, ACID Properties, and Indexing for Query Optimization

Welcome to Day 19 of your SQL journey! πŸš€ Today, we will explore two important topics:

1️⃣ Transactions & ACID Properties – Ensuring data consistency and integrity in databases.
2️⃣ Indexes – Speeding up queries and optimizing performance.

Both of these concepts are essential for maintaining a reliable and efficient database system. Let’s dive in!

---

πŸ”Ή 1. What is a Transaction in SQL?

A Transaction is a set of one or more SQL operations that are executed as a single unit of work.

βœ… If all operations are successful, the transaction is committed (saved permanently).
❌ If any operation fails, the transaction is rolled back (changes are undone).

---

πŸ” Example: Why Use Transactions?
Imagine a bank transfer:
1. Withdraw β‚Ή5000 from Account A
2. Deposit β‚Ή5000 to Account B

If the withdrawal is successful but the deposit fails, the money is lost! 😱

πŸ’‘ Solution? Use Transactions!

START TRANSACTION;

UPDATE Accounts SET Balance = Balance - 5000 WHERE AccountID = 1; -- Withdraw
UPDATE Accounts SET Balance = Balance + 5000 WHERE AccountID = 2; -- Deposit

COMMIT; -- Save changes if both updates succeed


βœ… If anything goes wrong, we can ROLLBACK:
ROLLBACK;  -- Undo changes if an error occurs


---

πŸ”Ή 2. Understanding ACID Properties

SQL transactions follow ACID properties to ensure reliability:

| ACID Property | Meaning | Explanation |
|---------------|---------|-------------|
| A**tomicity | All or Nothing | Either the entire transaction succeeds or everything is rolled back. |
| **C**onsistency | Valid Data Only | The database remains in a valid state before and after the transaction. |
| **I**solation | No Interference | Transactions do not affect each other while executing. |
| **D**urability | Changes are Permanent | Once committed, data changes **persist even after a system crash
. |

πŸ’‘ Example of ACID in Action:
START TRANSACTION;

UPDATE Orders SET Status = 'Shipped' WHERE OrderID = 101;
UPDATE Inventory SET Stock = Stock - 1 WHERE ProductID = 5;

COMMIT;

βœ”οΈ Atomicity: Both Orders and Inventory updates must succeed.
βœ”οΈ Consistency: Inventory should never go below 0.
βœ”οΈ Isolation: Other transactions shouldn’t affect this process.
βœ”οΈ Durability: The changes remain even after a crash.

---

πŸ”Ή 3. What is Indexing in SQL?

An Index is a database structure that improves the speed of data retrieval.

πŸ’‘ Think of it like the index page of a book – Instead of searching every page, you jump directly to the right section!

πŸ“Œ Why Use Indexes?
βœ… Faster SELECT queries
βœ… Efficient data lookup
βœ… Improves JOIN performance

---

πŸ”Ή 4. Types of Indexes in SQL

| Index Type | Description | Best Use Case |
|------------|-------------|---------------|
| Primary Index | Automatically created for Primary Key | Unique row identification |
| Unique Index | Ensures values in a column are unique | Email, Username fields |
| Clustered Index | Arranges data physically in table order | Sorting large datasets |
| Non-Clustered Index | Creates a separate lookup table | Speeding up searches |
| Full-Text Index | Used for searching text-heavy columns | Searching articles or descriptions |

---

πŸ”Ή 5. Creating and Using Indexes

πŸ“Œ Example: Creating an Index on a Single Column
CREATE INDEX idx_customer_lastname 
ON Customers (LastName);

βœ”οΈ Now, searching for a customer by LastName will be faster!

SELECT * FROM Customers WHERE LastName = 'Sharma';


---

πŸ“Œ Example: Creating a Unique Index
To ensure that Email IDs are unique, use:
CREATE UNIQUE INDEX idx_unique_email 
ON Customers (Email);

βœ”οΈ Prevents duplicate entries!

---

πŸ“Œ Example: Creating a Composite Index (Multiple Columns)
If we often search by FirstName + LastName, we create a composite index:
CREATE INDEX idx_name 
ON Customers (FirstName, LastName);

βœ”οΈ Now, queries like:
SELECT * FROM Customers WHERE FirstName = 'Amit' AND LastName = 'Kumar';

will be much faster! πŸš€

---

πŸ”Ή 6. When to Use and Avoid Indexes
❀1πŸ‘1
βœ… Use Indexes When:
βœ”οΈ Searching large datasets frequently (WHERE, JOIN, ORDER BY)
βœ”οΈ Columns contain unique values (Email, ID)

❌ Avoid Indexes When:
✘ The table has frequent INSERT/UPDATE/DELETE (Indexes slow down writes)
✘ The column has low uniqueness (Gender: Male/Female, Status: Active/Inactive)

---

πŸ”Ή 7. Deleting Indexes

If an index isn’t needed anymore, we can remove it:
DROP INDEX idx_customer_lastname;


βœ”οΈ This frees up storage and can speed up write operations.

---

πŸ“Œ Summary: Transactions vs. Indexing

| Feature | Transactions | Indexing |
|----------|-------------|----------|
| Purpose | Ensures data integrity | Improves query speed |
| Key Concept | ACID Properties | Search Optimization |
| Benefits | Reliable database operations | Faster data retrieval |
| Example | Bank Transfers | Searching Customers |

---

πŸ“Œ Your Tasks for Today
βœ… Practice Transactions: Try COMMIT and ROLLBACK
βœ… Create an Index: Test a Single and Composite Index
βœ… Experiment: Measure Query Speed with and without Indexes

Tomorrow, we will learn Stored Procedures and Functions in SQL! πŸš€

πŸ‘‰ Like ❀️ and Share if you’re excited for Day 20! 😊
πŸ‘3
Day 20: Error Handling in SQL & Writing Dynamic SQL Queries

Welcome to Day 20 of your SQL learning journey! πŸš€ Today, we will focus on two important topics:

1️⃣ Error Handling in SQL – How to manage and handle errors properly.
2️⃣ Dynamic SQL Queries – Writing flexible and customizable SQL queries.

These concepts will help you write robust, flexible, and efficient SQL code. Let’s dive in!

---

πŸ”Ή 1. Error Handling in SQL

❓ What is Error Handling?
Error handling in SQL is the process of detecting and responding to errors that occur during query execution.

Errors can happen due to:
βœ… Invalid data (e.g., inserting a string into a number column)
βœ… Violations of constraints (e.g., primary key duplication)
βœ… Syntax errors (e.g., missing commas, typos)
βœ… Deadlocks (when two transactions block each other)

To handle errors properly, SQL provides:
βœ”οΈ TRY…CATCH blocks
βœ”οΈ RAISEERROR (SQL Server) or SIGNAL (MySQL)
βœ”οΈ @@ERROR (SQL Server)

---

πŸ”Ή 2. TRY...CATCH in SQL (Error Handling Block)

The TRY…CATCH block helps catch errors and take appropriate action.

πŸ“Œ Syntax for TRY…CATCH in SQL Server:
BEGIN TRY
-- SQL Statements that might cause an error
END TRY
BEGIN CATCH
-- Code to handle the error
PRINT 'An error occurred: ' + ERROR_MESSAGE();
END CATCH;


---

πŸ“Œ Example: Handling a Division by Zero Error
BEGIN TRY
DECLARE @result INT;
SET @result = 10 / 0; -- This will cause an error (division by zero)
END TRY
BEGIN CATCH
PRINT 'Error: Division by zero is not allowed!';
END CATCH;

βœ”οΈ The CATCH block prevents the program from crashing and shows an error message.

---

πŸ”Ή 3. Using RAISEERROR in SQL Server

RAISEERROR is used to manually generate an error message.

πŸ“Œ Example: Raising a Custom Error
RAISEERROR ('Custom error: Something went wrong!', 16, 1);

βœ”οΈ 16 is the severity level (1 to 25)
βœ”οΈ 1 is the state (used for debugging)

---

πŸ”Ή 4. Using SIGNAL in MySQL

In MySQL, the SIGNAL statement is used for error handling.

πŸ“Œ Example: Raising an Error in MySQL
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Custom error: Invalid operation!';

βœ”οΈ 45000 represents a user-defined error.

---

πŸ”Ή 5. Writing Dynamic SQL Queries

❓ What is Dynamic SQL?
Dynamic SQL constructs SQL statements at runtime instead of using static queries.

βœ… Why Use Dynamic SQL?
βœ”οΈ Flexible Queries – Generate different queries dynamically
βœ”οΈ Conditional Execution – Run different SQL commands based on inputs
βœ”οΈ Table and Column Selection – Choose tables or columns dynamically

---

πŸ“Œ Example: Static vs. Dynamic SQL

Static SQL (Fixed Query)
SELECT * FROM Customers WHERE City = 'New York';

❌ Only works for New York – cannot change dynamically.

---

Dynamic SQL (Flexible Query)
DECLARE @CityName NVARCHAR(50);
SET @CityName = 'Los Angeles';

EXEC ('SELECT * FROM Customers WHERE City = ''' + @CityName + '''');

βœ”οΈ The query adapts to different cities dynamically!

---

πŸ”Ή 6. Using EXECUTE with Dynamic SQL

`EXEC` is used to run dynamically built queries.

πŸ“Œ Example: Using EXEC to Build a Query
DECLARE @TableName NVARCHAR(50);
SET @TableName = 'Customers';

EXEC ('SELECT * FROM ' + @TableName);

βœ”οΈ This query will run:
SELECT * FROM Customers;

---

πŸ”Ή 7. Using sp_executesql (More Secure)

`sp_executesql` is a safer way to run dynamic SQL because it allows parameterized queries.

πŸ“Œ Example: Using sp_executesql for Dynamic SQL
DECLARE @SQLQuery NVARCHAR(1000);
DECLARE @CityName NVARCHAR(50);
SET @CityName = 'Chicago';

SET @SQLQuery = 'SELECT * FROM Customers WHERE City = @City';

EXEC sp_executesql @SQLQuery, N'@City NVARCHAR(50)', @CityName;

βœ”οΈ Prevents SQL injection (unlike EXEC)
βœ”οΈ More readable and maintainable

---

πŸ”Ή 8. When to Use Dynamic SQL?

βœ… Use Dynamic SQL When:
βœ”οΈ Query structure changes based on user input
βœ”οΈ Tables or columns change dynamically
βœ”οΈ Running complex search filters
❌ Avoid Dynamic SQL When:
✘ Queries are simple and don’t need customization
✘ Can use stored procedures instead
✘ Security is a concern (improper EXEC usage can cause SQL injection attacks)

---

πŸ“Œ Summary: Error Handling & Dynamic SQL

| Feature | Error Handling | Dynamic SQL |
|----------|---------------|-------------|
| Purpose | Manage & respond to errors | Generate flexible queries dynamically |
| Key Techniques | TRY…CATCH, RAISEERROR, SIGNAL | EXEC, sp_executesql |
| Best Use Cases | Prevent query failures | Handle dynamic tables & user inputs |
| Security Concern | Avoid crashes & failures | Prevent SQL Injection |

---

πŸ“Œ Your Tasks for Today
βœ… Write a TRY…CATCH block to handle errors in a SQL statement
βœ… Practice using RAISEERROR or SIGNAL to generate custom error messages
βœ… Create a dynamic SQL query using EXEC and sp_executesql

Tomorrow, we will explore Stored Procedures and Functions in SQL! πŸš€

πŸ‘‰ Like ❀️ and Share if you’re excited for Day 21! 😊
❀1
Day 21: Week 3 Review & Advanced SQL Challenges

Welcome to Day 21 of your SQL journey! πŸš€ You’ve covered some powerful SQL concepts in Week 3. Today, we will:

βœ… Review key topics from Week 3
βœ… Practice complex SQL queries
βœ… Solve intermediate to advanced SQL challenges

Let’s strengthen your skills and boost your confidence with real-world SQL problems! πŸ’ͺ

---

πŸ”Ή Week 3 Review: What We Covered

πŸ“Œ Day 15: Common Table Expressions (CTEs)
CTEs allow you to create temporary result sets inside a query.

Example: Simple CTE
WITH EmployeeCTE AS (
SELECT EmployeeID, Name, Salary
FROM Employees
WHERE Salary > 50000
)
SELECT * FROM EmployeeCTE;

βœ”οΈ Makes queries more readable and reusable!

---

πŸ“Œ Day 16-17: Window Functions
Window functions help perform ranking, calculations, and comparisons across rows.

Example: Ranking Employees by Salary
SELECT EmployeeID, Name, Salary, 
RANK() OVER (ORDER BY Salary DESC) AS Rank
FROM Employees;

βœ”οΈ Assigns a rank based on salary, without grouping the data!

---

πŸ“Œ Day 18: Views & Temporary Tables
- Views: Virtual tables based on a SQL query.
- Temporary Tables: Store data for a session.

Example: Creating a View for High-Salary Employees
CREATE VIEW HighSalaryEmployees AS
SELECT EmployeeID, Name, Salary
FROM Employees
WHERE Salary > 60000;

βœ”οΈ Helps simplify complex queries!

---

πŸ“Œ Day 19: Transactions & Indexes
- Transactions ensure data consistency with ACID properties.
- Indexes speed up queries by optimizing searches.

Example: Using Transactions
BEGIN TRANSACTION;
UPDATE Accounts SET Balance = Balance - 500 WHERE AccountID = 1;
UPDATE Accounts SET Balance = Balance + 500 WHERE AccountID = 2;
COMMIT;

βœ”οΈ Ensures money transfer happens completely or not at all!

---

πŸ“Œ Day 20: Error Handling & Dynamic SQL
- Error Handling: TRY…CATCH, RAISEERROR, SIGNAL.
- Dynamic SQL: Generates queries at runtime.

Example: Dynamic SQL to Filter Customers by City
DECLARE @CityName NVARCHAR(50);
SET @CityName = 'Los Angeles';

EXEC ('SELECT * FROM Customers WHERE City = ''' + @CityName + '''');

βœ”οΈ Allows queries to change dynamically based on user input!

---

πŸ”Ή SQL Challenge Practice: Intermediate to Advanced

Let’s apply these concepts with real-world SQL challenges! πŸ†

---

Challenge 1: Find Employees with the Second Highest Salary
πŸ’‘ Problem: Retrieve the second highest salary from the Employees table.

πŸ“Œ Solution: Using DISTINCT & LIMIT
SELECT DISTINCT Salary 
FROM Employees
ORDER BY Salary DESC
LIMIT 1 OFFSET 1;

βœ”οΈ `OFFSET 1` skips the highest salary and picks the second-highest!

πŸ“Œ Solution: Using `RANK()`
WITH SalaryRanking AS (
SELECT Salary, RANK() OVER (ORDER BY Salary DESC) AS rnk
FROM Employees
)
SELECT Salary FROM SalaryRanking WHERE rnk = 2;

βœ”οΈ More efficient when handling duplicate salaries!

---

Challenge 2: Find Departments with More than 5 Employees
πŸ’‘ Problem: Retrieve all departments where employee count is greater than 5.

πŸ“Œ Solution: Using GROUP BY & HAVING
SELECT DepartmentID, COUNT(*) AS EmployeeCount
FROM Employees
GROUP BY DepartmentID
HAVING COUNT(*) > 5;

βœ”οΈ HAVING filters results after aggregation!

---

Challenge 3: Find Consecutive Employee Absences
πŸ’‘ Problem: Identify employees who were absent 3 days in a row.

πŸ“Œ Solution: Using `LAG()`
WITH AbsenceData AS (
SELECT EmployeeID, AbsenceDate,
LAG(AbsenceDate, 1) OVER (PARTITION BY EmployeeID ORDER BY AbsenceDate) AS PrevDay1,
LAG(AbsenceDate, 2) OVER (PARTITION BY EmployeeID ORDER BY AbsenceDate) AS PrevDay2
FROM Attendance
)
SELECT EmployeeID, AbsenceDate
FROM AbsenceData
WHERE DATEDIFF(AbsenceDate, PrevDay1) = 1
AND DATEDIFF(PrevDay1, PrevDay2) = 1;

βœ”οΈ `LAG()` compares current and previous rows!

---

Challenge 4: Detect Duplicate Customer Records
πŸ’‘ Problem: Find duplicate customers in the Customers table.
❀1πŸ‘1
πŸ“Œ Solution: Using GROUP BY
SELECT Name, Email, COUNT(*) AS DuplicateCount
FROM Customers
GROUP BY Name, Email
HAVING COUNT(*) > 1;

βœ”οΈ Helps identify and clean duplicate data!

---

Challenge 5: Monthly Revenue Analysis
πŸ’‘ Problem: Find total revenue per month in the Sales table.

πŸ“Œ Solution: Using `DATE_FORMAT()` (MySQL)
SELECT DATE_FORMAT(SaleDate, '%Y-%m') AS Month, SUM(Revenue) AS TotalRevenue
FROM Sales
GROUP BY Month;

βœ”οΈ Extracts month-year format and calculates revenue!

---
πŸ”Ή What You Achieved Today! 🎯
βœ… Reviewed all major topics from Week 3
βœ… Practiced writing advanced SQL queries
βœ… Solved real-world SQL problems

---

πŸ”Ή Your Tasks for Today
1️⃣ Try the SQL challenges above in your database.
2️⃣ Modify queries to test different scenarios.
3️⃣ Post your SQL solutions & doubts in the comments!

Tomorrow, we move to Stored Procedures & Functions in SQL! πŸš€

πŸ‘‰ Like ❀️ & Share if you're excited for Day 22! 😊
Day 22: Database Design & Normalization

Welcome to Day 22 of your SQL learning journey! πŸš€
Today, we will cover Database Design and Normalization, which helps in organizing data efficiently in a database.

πŸ”Ή What is Normalization?
πŸ”Ή Why do we need it?
πŸ”Ή Understanding 1NF, 2NF, 3NF, and BCNF with simple explanations and examples.

By the end of this lesson, you will be able to design efficient databases that reduce redundancy and improve performance! 🎯

---

πŸ”Ή What is Normalization?

πŸ”Ή Normalization is the process of organizing database tables to:
βœ”οΈ Reduce data redundancy (duplicate data).
βœ”οΈ Improve data integrity (accuracy & consistency).
βœ”οΈ Avoid insertion, update, and deletion anomalies.
βœ”οΈ Make queries faster and efficient.

---

πŸ”Ή Why Do We Need Normalization?

πŸ’‘ Problem Without Normalization

Imagine a Students table with the following data:

| StudentID | Name | Course | Instructor | InstructorPhone |
|-----------|--------|-------------|-------------|-----------------|
| 1 | John | SQL Basics | Mr. Smith | 9876543210 |
| 2 | Alice | Python | Ms. Brown | 8765432109 |
| 3 | John | Python | Ms. Brown | 8765432109 |

πŸ”΄ Issues in this table:
1️⃣ Duplicate data (John appears twice).
2️⃣ Update Anomaly: If Ms. Brown’s phone number changes, we must update multiple records.
3️⃣ Insertion Anomaly: If a new instructor is added but no student has enrolled yet, we cannot store their details.
4️⃣ Deletion Anomaly: If the last student in a course is removed, we lose instructor information.

πŸ‘‰ Solution? Apply Normalization!

---
πŸ”Ή Types of Normal Forms (NF)

βœ… 1NF (First Normal Form) – Remove Duplicate Columns & Ensure Atomicity

A table is in 1NF if:
βœ”οΈ All columns contain atomic values (indivisible).
βœ”οΈ Each column has only one value per row.
βœ”οΈ There are no duplicate columns.

πŸ”΄ Problem (Not in 1NF)
| StudentID | Name | Courses | Instructor |
|-----------|-------|--------------------|---------------|
| 1 | John | SQL, Python | Smith, Brown |
| 2 | Alice | Python | Brown |

πŸ”΄ Issues:
βœ”οΈ Courses contain multiple values in one column (SQL, Python).
βœ”οΈ Instructors are not separated properly.

βœ… Solution (1NF Table)
| StudentID | Name | Course | Instructor |
|-----------|-------|---------|------------|
| 1 | John | SQL | Smith |
| 1 | John | Python | Brown |
| 2 | Alice | Python | Brown |

βœ”οΈ Each value is atomic.
βœ”οΈ No multiple values in a single column.

---

βœ… 2NF (Second Normal Form) – Remove Partial Dependency

A table is in 2NF if:
βœ”οΈ It is already in 1NF.
βœ”οΈ Every non-key column is fully dependent on the primary key.

πŸ”΄ Problem (Not in 2NF)
| StudentID | Name | Course | Instructor | InstructorPhone |
|-----------|-------|---------|------------|-----------------|
| 1 | John | SQL | Smith | 9876543210 |
| 1 | John | Python | Brown | 8765432109 |
| 2 | Alice | Python | Brown | 8765432109 |

πŸ”΄ Issues:
βœ”οΈ Instructor’s phone number depends only on Instructor, not StudentID.
βœ”οΈ If an instructor's phone number changes, we must update multiple records.

βœ… Solution (2NF Tables - Splitting into Two Tables)

πŸ‘‰ Students Table
| StudentID | Name | Course | Instructor |
|-----------|-------|---------|------------|
| 1 | John | SQL | Smith |
| 1 | John | Python | Brown |
| 2 | Alice | Python | Brown |

πŸ‘‰ Instructors Table
| Instructor | InstructorPhone |
|-----------|-----------------|
| Smith | 9876543210 |
| Brown | 8765432109 |

βœ”οΈ Now, InstructorPhone depends only on Instructor, not StudentID!

---

βœ… 3NF (Third Normal Form) – Remove Transitive Dependency

A table is in 3NF if:
βœ”οΈ It is already in 2NF.
βœ”οΈ No non-key column depends on another non-key column.
πŸ”΄ Problem (Not in 3NF)
| StudentID | Name | Course | Instructor | InstructorPhone | InstructorEmail |
|-----------|-------|---------|------------|-----------------|-----------------|
| 1 | John | SQL | Smith | 9876543210 | smith@email.com |
| 1 | John | Python | Brown | 8765432109 | brown@email.com |

πŸ”΄ Issue:
βœ”οΈ InstructorPhone & InstructorEmail depend on Instructor, not StudentID.

βœ… Solution (3NF - Creating a Separate Instructor Table)

πŸ‘‰ Students Table
| StudentID | Name | Course | Instructor |
|-----------|-------|---------|------------|
| 1 | John | SQL | Smith |
| 1 | John | Python | Brown |
| 2 | Alice | Python | Brown |

πŸ‘‰ Instructors Table
| Instructor | InstructorPhone | InstructorEmail |
|------------|----------------|-----------------|
| Smith | 9876543210 | smith@email.com |
| Brown | 8765432109 | brown@email.com |

βœ”οΈ Now, no non-key column depends on another non-key column!

---

βœ… BCNF (Boyce-Codd Normal Form) – Stronger than 3NF

A table is in BCNF if:
βœ”οΈ It is already in 3NF.
βœ”οΈ Every determinant is a candidate key (i.e., no partial dependency at all).

πŸ”΄ Problem (Not in BCNF)
| Course | Instructor | Room |
|--------|------------|------|
| SQL | Smith | A101 |
| Python | Brown | A102 |
| Python | Lee | A102 |

πŸ”΄ Issue:
βœ”οΈ Room depends on Course & Instructor, not on Course alone.

βœ… Solution (BCNF - Splitting the Table)
πŸ‘‰ Courses Table
| Course | Instructor |
|---------|------------|
| SQL | Smith |
| Python | Brown |
| Python | Lee |

πŸ‘‰ Room Assignment Table
| Instructor | Room |
|------------|------|
| Smith | A101 |
| Brown | A102 |
| Lee | A102 |

βœ”οΈ Now, every determinant is a candidate key!

---

# πŸ”Ή Summary

| Normalization Level | Fixes |
|----------------------|--------------------------------|
| 1NF | Remove duplicate columns & ensure atomicity |
| 2NF | Remove partial dependency |
| 3NF | Remove transitive dependency |
| BCNF | Remove all redundancy |

---

πŸ”Ή Your Task for Today
βœ… Normalize a messy database you’ve worked with before.
βœ… Share your doubts or SQL questions in the comments!

Tomorrow, we move to Constraints in SQL! πŸš€

πŸ‘‰ Like ❀️ & Share if you're enjoying the SQL series! 😊
πŸ‘4
Day 23: Constraints in SQL πŸš€

Welcome to Day 23 of your SQL journey! Today, we will cover SQL Constraints in depth.

πŸ”Ή What are Constraints in SQL?
Constraints control the rules for the data stored in a database table. They ensure accuracy, integrity, and consistency of the data.

πŸ‘‰ Constraints help in preventing invalid data from being inserted.

πŸ“Œ Today, we will learn about:
βœ”οΈ PRIMARY KEY
βœ”οΈ FOREIGN KEY
βœ”οΈ UNIQUE
βœ”οΈ CHECK
βœ”οΈ DEFAULT

---

πŸ”Ή 1. PRIMARY KEY Constraint

A PRIMARY KEY uniquely identifies each record in a table.
βœ”οΈ A table can have only one PRIMARY KEY.
βœ”οΈ The PRIMARY KEY column cannot have NULL values.
βœ”οΈ It must be unique for every row.

βœ… Example of PRIMARY KEY
CREATE TABLE Students (
StudentID INT PRIMARY KEY,
Name VARCHAR(50),
Age INT
);

βœ”οΈ StudentID is the PRIMARY KEY, meaning each student must have a unique ID and it cannot be NULL.

βœ… Inserting Data (Valid & Invalid Cases)
INSERT INTO Students (StudentID, Name, Age) VALUES (1, 'Alice', 20); -- βœ… Valid
INSERT INTO Students (StudentID, Name, Age) VALUES (2, 'Bob', 22); -- βœ… Valid
INSERT INTO Students (StudentID, Name, Age) VALUES (1, 'Charlie', 25); -- ❌ Error! Duplicate StudentID
INSERT INTO Students (StudentID, Name, Age) VALUES (NULL, 'David', 23); -- ❌ Error! NULL not allowed


---

πŸ”Ή 2. FOREIGN KEY Constraint

A FOREIGN KEY creates a link between two tables.
βœ”οΈ It ensures referential integrity (data in the foreign key column must exist in the referenced table).
βœ”οΈ It prevents orphan records (a record that refers to a non-existing row in another table).

βœ… Example of FOREIGN KEY
CREATE TABLE Courses (
CourseID INT PRIMARY KEY,
CourseName VARCHAR(50)
);

CREATE TABLE Enrollments (
EnrollmentID INT PRIMARY KEY,
StudentID INT,
CourseID INT,
FOREIGN KEY (StudentID) REFERENCES Students(StudentID),
FOREIGN KEY (CourseID) REFERENCES Courses(CourseID)
);

βœ”οΈ `StudentID` in Enrollments table must exist in the Students table.
βœ”οΈ `CourseID` in Enrollments table must exist in the Courses table.

βœ… Inserting Data (Valid & Invalid Cases)
INSERT INTO Courses (CourseID, CourseName) VALUES (101, 'SQL Basics'); -- βœ… Valid
INSERT INTO Enrollments (EnrollmentID, StudentID, CourseID) VALUES (1, 1, 101); -- βœ… Valid (Student 1 exists)
INSERT INTO Enrollments (EnrollmentID, StudentID, CourseID) VALUES (2, 5, 101); -- ❌ Error! Student 5 does not exist


---

πŸ”Ή 3. UNIQUE Constraint

Ensures all values in a column are unique, but it allows NULL values (unlike PRIMARY KEY).
βœ”οΈ Prevents duplicate values in a column.
βœ”οΈ A table can have multiple UNIQUE constraints (unlike PRIMARY KEY).

βœ… Example of UNIQUE Constraint
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
Email VARCHAR(100) UNIQUE,
Phone VARCHAR(15) UNIQUE
);

βœ”οΈ EmployeeID is the PRIMARY KEY (must be unique & non-null).
βœ”οΈ Email and Phone must be unique, but they can be NULL.

βœ… Inserting Data (Valid & Invalid Cases)
INSERT INTO Employees (EmployeeID, Email, Phone) VALUES (1, 'alice@email.com', '1234567890'); -- βœ… Valid
INSERT INTO Employees (EmployeeID, Email, Phone) VALUES (2, 'bob@email.com', '9876543210'); -- βœ… Valid
INSERT INTO Employees (EmployeeID, Email, Phone) VALUES (3, 'alice@email.com', '5678901234'); -- ❌ Error! Duplicate Email
INSERT INTO Employees (EmployeeID, Email, Phone) VALUES (4, NULL, '5678901234'); -- βœ… Valid (NULL allowed in UNIQUE)


---

πŸ”Ή 4. CHECK Constraint

CHECK ensures that column values meet specific conditions.
βœ”οΈ Used to enforce business rules (e.g., Age must be greater than 18).

βœ… Example of CHECK Constraint
CREATE TABLE Customers (
CustomerID INT PRIMARY KEY,
Name VARCHAR(50),
Age INT CHECK (Age >= 18)
);

βœ”οΈ Ensures that Age must be 18 or older.

βœ… Inserting Data (Valid & Invalid Cases)
INSERT INTO Customers (CustomerID, Name, Age) VALUES (1, 'Alice', 25); -- βœ… Valid
INSERT INTO Customers (CustomerID, Name, Age) VALUES (2, 'Bob', 17); -- ❌ Error! Age must be >= 18


---

πŸ”Ή 5. DEFAULT Constraint