Welcome To SQL Tutorial!

1. Getting Set Up (Installation)

Before we can write any code, we need to install MySQL on your computer. Think of this as downloading the "brain" of the database. Without this brain, your computer has no idea how to store, read, or organize database files.

Setting up your environment can sometimes be the hardest part of learning to code, but do not worry. We will take it one simple step at a time!

Step 1: Download the Installer

  • Go to the official MySQL website and download the MSI Installer for Windows.
  • Pick the bigger file (around 500MB+). It has everything you need bundled inside, so you don't have to download pieces separately from the internet during installation.
  • Just click "No thanks, just start my download" when it asks you to log in. You don't need an Oracle account to use MySQL!

Step 2: Run the Setup

  • Open the file you just downloaded. It might take a minute to load.
  • When it asks what kind of setup you want, pick Developer Default. This gives you the server itself (the invisible engine running in the background) and a nice visual app called MySQL Workbench to interact with it easily. Click Next and Execute to let it install.

Step 3: The Most Important Step (Your Password!)

  • Keep the default network settings (Port 3306). Think of port 3306 as the specific "door" on your computer that MySQL uses to listen for instructions.
  • Choose Strong Password Encryption to keep your data safe.
  • Create a Root Password: You are the "root" user (the ultimate admin with unlimited power). Make a password and write it down somewhere safe! If you lose this, you will be permanently locked out of your own local database and will have to reinstall everything.

Step 4: Test it out!

  • Open your Windows Start Menu and search for MySQL Command Line Client.
  • Type in that root password you just created.
  • If you see a welcome message and a mysql> prompt popping up, congratulations! You successfully installed your very first database server.

2. Connecting to VS Code

If you already use Visual Studio Code for your HTML, CSS, or Python programming, you can actually manage your database right from there! Why is this great? Because switching between three different apps just to write some code gets annoying fast.

By bringing MySQL into VS Code, you can write your website code and check your database tables all in the exact same window.

Step 1: Get the Extensions

  • Open VS Code, go to the Extensions tab on the left sidebar (the icon looks like four blocks), and search for SQLTools. Install the main one.
  • Then, search for and install its companion driver: SQLTools MySQL/MariaDB/TiDB. This driver acts like a translator so VS Code can speak MySQL's specific language.

Step 2: Link them up

  • Click the new database icon on your sidebar (it looks like a little cylinder) and hit Add New Connection.
  • Choose the MySQL option from the list of database types.
  • Fill in the blanks to tell VS Code where to find your database:
    • Connection Name: My Local DB (or whatever friendly name you want to give it)
    • Server Address: localhost (This is a special computer term that just means "look inside my own computer, not on the internet")
    • Port: 3306 (Remember the door we talked about during installation?)
    • Username: root (Because you are the boss!)
  • Save it, click Connect Now, type your master password when prompted, and you're officially ready to write SQL code!

3. What Actually is a Database?

Before typing code, let's understand what we are making. A database is simply a highly organized digital filing cabinet designed to store massive amounts of information quickly and safely.

If you tried to store 10 million user accounts in a simple text file, your computer would freeze trying to read it. Databases fix this problem!

MySQL is what we call a Relational Database. All "relational" means is that your data is stored in neat, organized tables that look exactly like Microsoft Excel spreadsheets, and these tables can be connected (related) to each other.

  • Table: The spreadsheet itself. For example, you might have one table for "Students" and a completely separate table for "Teachers".
  • Row (Record): One horizontal line of data. If we look at row number 5, it might contain all of Ali's personal information (his ID, his name, his grade).
  • Column (Field): A vertical category. Every piece of data in the "First Name" column will only ever be a first name. You can't put a date inside a name column!

4. Building Your Database (DDL)

DDL stands for Data Definition Language. This is the part of SQL we use to build the actual structures. Think of DDL like a construction worker: it builds the warehouse, puts up the walls, and builds the empty shelves.

Let's build a university database from scratch!

Creating the Database File

Use the CREATE DATABASE command to make a new empty file. Then, use USE to tell the computer you actually want to open it and work inside it.

/* Creates the empty warehouse */
CREATE DATABASE cbs_university;

/* Opens the doors so we can go inside */
USE cbs_university;

Line-by-line breakdown:

  • CREATE DATABASE cbs_university;: This tells MySQL to carve out some space on your hard drive and label it 'cbs_university'. We always end statements with a semicolon (;)!
  • USE cbs_university;: You might have 50 databases on your computer. This line explicitly selects this specific one to be active so we don't accidentally put our tables in the wrong place.

Creating a Table

Now let's make a spreadsheet (table) to hold our students. We have to tell MySQL exactly what columns we want before we put any data inside.

CREATE TABLE Students (
    StudentID int PRIMARY KEY,
    FirstName varchar(50),
    LastName varchar(50),
    EnrollmentYear int
);

Line-by-line breakdown:

  • CREATE TABLE Students (: We are creating a new table named 'Students' and opening parentheses to list our columns.
  • StudentID int PRIMARY KEY,: Our first column is StudentID. int means "integer" (whole numbers only). PRIMARY KEY is a super important rule: it means every single student MUST have a unique ID, and it cannot be blank. No two students can be student number 1!
  • FirstName varchar(50),: Our second column is for the first name. varchar(50) stands for "variable characters", meaning it holds text up to a maximum of 50 letters.
  • LastName varchar(50),: Same thing here, a text column for the last name.
  • EnrollmentYear int: A whole number column to hold the year they joined. Notice there is no comma on the very last line!
  • );: We close our parentheses and add our semicolon to finish the command.

5. Adding & Changing Data (DML)

Now we have a completely empty table with perfect columns. Let's put some students in it! We use DML (Data Manipulation Language) for this. If DDL built the warehouse shelves, DML is the worker placing boxes onto those shelves.

Adding New Data (INSERT INTO)

You need to tell the computer which table to use, which columns you are filling out, and what the actual values are.

/* Adding a new student to our table */
INSERT INTO Students (StudentID, FirstName, LastName, EnrollmentYear)
VALUES (1, 'Ali', 'Khan', 2023);

Line-by-line breakdown:

  • INSERT INTO Students ...: We are targeting the Students table. Inside the parentheses, we list out the exact columns we plan to give data to.
  • VALUES (1, 'Ali', 'Khan', 2023);: These are the actual details. Notice how text like 'Ali' has single quotes around it, but numbers like 1 and 2023 do not! The order of these values MUST match the order of the columns listed above perfectly.

Changing Existing Data (UPDATE)

Did someone's enrollment year change, or did we spell their name wrong? Use UPDATE. CRITICAL RULE: Always use the WHERE clause to specify exactly WHO you are updating.

If you forget the WHERE clause, you will accidentally overwrite the data of every single student in the whole school at the exact same time! It is the most common mistake beginners make.

/* Fixing an enrollment mistake */
UPDATE Students
SET EnrollmentYear = 2024
WHERE StudentID = 1;

Line-by-line breakdown:

  • UPDATE Students: Target the Students table for editing.
  • SET EnrollmentYear = 2024: This is the change we want to make. We are setting the year to 2024.
  • WHERE StudentID = 1;: The safety lock! This guarantees we only change the year for the specific student who has ID number 1. Everyone else is left alone.

Deleting Data (DELETE)

Sometimes a student leaves the university and we need to remove their record entirely. The exact same safety rule applies here—do not forget WHERE, or you will delete the whole table!

/* Removing a student who left */
DELETE FROM Students
WHERE StudentID = 4;

Line-by-line breakdown:

  • DELETE FROM Students: Get ready to remove entire rows from the Students table.
  • WHERE StudentID = 4;: Only delete the single row where the ID is 4. The student is now gone from our system.

6. Searching for Data

Fetching data is what you will do 90% of the time as a developer. Think about it: when you open Instagram, you aren't adding a new account, you are asking Instagram to fetch and show you pictures. We use the SELECT command to ask the database questions.

Show Me Everything

The asterisk (*) is a magical shortcut in SQL that translates to "all columns". It is the easiest way to see everything in a table.

/* Pulls up the entire spreadsheet */
SELECT * FROM Students;

Line-by-line breakdown:

  • SELECT *: "Give me every single column..."
  • FROM Students;: "...that exists inside the Students table."

Filtering with WHERE

You rarely want to see every single piece of data at once. What if you only want to see students from a specific year? We use WHERE to filter our search.

/* Finding the class of 2023 */
SELECT * FROM Students
WHERE EnrollmentYear = 2023;

Line-by-line breakdown:

  • SELECT * FROM Students: Grab the whole table...
  • WHERE EnrollmentYear = 2023;: ...but only show me the rows on the screen if their enrollment year matches 2023 exactly. Hide everyone else!

Making Titles Prettier (AS)

In our database, we named our column FirstName without spaces because computers hate spaces. But if we are printing a report for a boss, that looks ugly. We can give columns a temporary nickname using AS (which stands for Alias).

/* Making the output look clean */
SELECT FirstName AS 'First Name' FROM Students;

Line-by-line breakdown:

  • SELECT FirstName: Only grab the first name column this time (no asterisk!).
  • AS 'First Name': When you print it on the screen, change the header to say "First Name" with a nice space in the middle.
  • FROM Students;: Pull it from our target table.

7. Sorting & Organizing

If you have 10,000 students in your system, you can't just look at them in whatever random order they were typed in. You need to organize them so they make sense to human eyes.

Alphabetical / Number Order (ORDER BY)

We can put things in A-Z order, or use DESC (descending) to flip it backwards (Z-A, or highest number to lowest number).

/* Alphabetical list of students */
SELECT * FROM Students
ORDER BY FirstName ASC;

Line-by-line breakdown:

  • SELECT * FROM Students: Fetch everyone from the table.
  • ORDER BY FirstName ASC;: Before showing me the result, organize the rows based on their first names. ASC stands for Ascending (A to Z). If we wanted Z to A, we would type DESC.

Limiting Results (LIMIT)

What if you only want to see the very top 2 students? Or what if a website only shows 10 products per page? We use LIMIT to stop the database from giving us too much data.

/* Show me just the first two people */
SELECT * FROM Students
LIMIT 2;

Line-by-line breakdown:

  • SELECT * FROM Students: Fetch the data...
  • LIMIT 2;: ...but the second you find 2 rows, stop searching and give me the result. Ignore the rest of the table entirely.

8. Doing the Math (Aggregate Functions)

Databases are incredibly fast at doing math. Instead of pulling all the data to your website and writing Python or JavaScript code to count it, you can just ask the database to do the math for you!

  • COUNT(): Counts how many total rows exist.
  • SUM(): Adds number values together (like finding the total of all shopping carts).
  • AVG(): Finds the mathematical average (like finding the average test score).
  • MAX() & MIN(): Finds the highest or lowest number in a column.

Example: How many students do we have?

Instead of pulling all the names, let's just ask for the total headcount.

/* Doing a quick headcount */
SELECT COUNT(StudentID) AS TotalStudents FROM Students;

Line-by-line breakdown:

  • SELECT COUNT(StudentID): Look at the StudentID column and count exactly how many rows have an ID inside them.
  • AS TotalStudents: Make the result title look pretty by naming it "TotalStudents".
  • FROM Students;: Calculate this from the Students table.

Grouping Data (GROUP BY)

What if we want a more detailed breakdown? If you want to know how many students joined each specific year, you group them up by their year first, and then count them!

/* Counting students per year */
SELECT EnrollmentYear, COUNT(StudentID) 
FROM Students
GROUP BY EnrollmentYear;

Line-by-line breakdown:

  • SELECT EnrollmentYear, COUNT(StudentID): Show me the year, and show me the count of students right next to it.
  • FROM Students: Look in our table.
  • GROUP BY EnrollmentYear;: This groups identical years into piles. All the 2023 students go in one pile, and 2024 in another. Then, the COUNT function counts the size of each pile!

9. Connecting Tables Together (JOINS)

In the real world, you do not put all your data in one massive, 100-column spreadsheet. It gets too messy. Instead, you separate them logically (like having a "Students" table and a "Courses" table) and link them together using those unique IDs we talked about earlier!

This linking process is called a JOIN. It is like taking two separate spreadsheets and gluing them together side-by-side whenever the IDs match up.

INNER JOIN

This is the most common join. It smushes the two tables together but ONLY shows a result if there is a perfect match in both tables. For example, it only shows students who are actually enrolled in a course.

/* Matching students to their classes */
SELECT Students.FirstName, Courses.CourseName
FROM Students
INNER JOIN Courses 
ON Students.StudentID = Courses.StudentID;

Line-by-line breakdown:

  • SELECT Students.FirstName, Courses.CourseName: We tell the database exactly which columns we want, and notice we put the table name first (Table.Column). This avoids confusion!
  • FROM Students: We start with our primary table.
  • INNER JOIN Courses: We tell it to grab the second table, Courses, and glue it to the first one.
  • ON Students.StudentID = Courses.StudentID;: This is the rule for the glue! We tell it to connect a row only when the StudentID from the first table perfectly matches the StudentID in the second table.

LEFT JOIN

Sometimes you want to see everyone, even if they don't match. A LEFT JOIN shows ALL the records from your first table (the left one), regardless of matches.

If we used a LEFT JOIN here, it would print out every single student in the whole university. If a student hasn't signed up for a course yet, the computer won't hide them; their course name will just show up as a big empty blank called NULL.

10. Leveling Up (Advanced)

Once you master the basics, you can start using SQL to enforce business rules and solve complex logical puzzles.

Strict Rules (Constraints)

You can force your tables to be strict about what data is allowed inside them. This stops bad data from breaking your website later!

  • NOT NULL: This means the column is completely mandatory. If someone tries to save a record without filling this out, the database throws an error.
  • UNIQUE: This guarantees data cannot be repeated. It is perfect for things like Usernames or Email addresses where duplicates would cause chaos.
/* Creating a strict table */
CREATE TABLE Teachers (
    TeacherID int PRIMARY KEY,
    Email varchar(100) UNIQUE NOT NULL,
    Name varchar(50) NOT NULL
);

Line-by-line breakdown:

  • TeacherID int PRIMARY KEY,: Unique ID for the teacher.
  • Email varchar(100) UNIQUE NOT NULL,: This creates an email column up to 100 letters long. UNIQUE ensures no two teachers share an email, and NOT NULL means they absolutely must provide one!
  • Name varchar(50) NOT NULL: They must provide a name, it cannot be blank.

Subqueries (Query Inception!)

A subquery is just a query inside another query. The database is smart enough to solve the "inside" puzzle first, and then it uses that hidden answer to solve the "outside" puzzle.

Imagine you don't know the ID code for 'Data Structures', but you need to find all the students taking it. A subquery solves this instantly.

/* Finding students in a specific class without knowing the ID */
SELECT FirstName, LastName 
FROM Students
WHERE StudentID IN (
    SELECT StudentID 
    FROM Courses 
    WHERE CourseName = 'Data Structures'
);

Line-by-line breakdown:

  • SELECT FirstName, LastName FROM Students: The outside puzzle. We want names from the Students table.
  • WHERE StudentID IN ( ... ): But we only want students whose IDs match the list we are about to generate inside the parentheses.
  • SELECT StudentID FROM Courses WHERE CourseName = 'Data Structures': The inside puzzle! The computer runs this first. It finds all the IDs for Data Structures (let's say it finds IDs 5, 9, and 12). It passes those numbers back out, and the main query fetches those specific students!