<?php OOP: Zero to Hero Chapter 14 of 20

Chapter 14 ยท Databases & Forms

Databases, Tables & SQL

So far, all our data vanishes the instant the page finishes loading โ€” variables live only for one request. Real applications need memory that survives: a database. This chapter introduces MySQL, tables, and the language used to talk to them: SQL.

๐Ÿ—„๏ธ
Real-world analogy

A database is a filing cabinet. Each table is one drawer dedicated to one kind of thing (a drawer for students, a drawer for courses). Inside a drawer, every row is one filled-in record card (one actual student), and the columns are the labelled blanks that every card shares (name, program, fee). SQL is the polite language you use to ask the filing clerk to add, find, change or remove cards.

Meet phpMyAdmin

XAMPP ships with phpMyAdmin, a friendly web page for managing MySQL. With Apache and MySQL running, visit:

http://localhost/phpmyadmin

You'll see existing databases on the left. We'll create our own. You can do everything by clicking buttons โ€” but we'll learn the SQL commands too, because buttons don't work from PHP; SQL does. In phpMyAdmin, click the SQL tab to type commands directly.

Creating a database and a table

CREATE DATABASE school_db;

USE school_db;

CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    student_number VARCHAR(20) NOT NULL UNIQUE,
    full_name VARCHAR(100) NOT NULL,
    program VARCHAR(100) NOT NULL,
    fee_balance DECIMAL(10,2) DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Let's decode every piece โ€” this vocabulary appears in every project you will ever build:

PiecePlain meaning
INTWhole numbers
VARCHAR(100)Text up to 100 characters
DECIMAL(10,2)Exact decimal number: up to 10 digits, 2 after the point โ€” always use this for money, never FLOAT
TIMESTAMPA date and time
NOT NULLThis blank may never be left empty
UNIQUENo two rows may share this value
DEFAULT ...The value used if none is provided
AUTO_INCREMENTMySQL numbers the rows itself: 1, 2, 3โ€ฆ
PRIMARY KEYThe column that uniquely identifies each row โ€” its "NRC number"
Why every table needs an id

Names can repeat (two students called John Banda!), but the auto-incrementing id never does. When we later edit or delete a record, we always point at it by id. Every table you ever design should start with id INT AUTO_INCREMENT PRIMARY KEY.

INSERT โ€” adding rows

INSERT INTO students (student_number, full_name, program, fee_balance)
VALUES ('LGU2026-001', 'Chanda Mwila', 'BSc Computing', 5000.00);

INSERT INTO students (student_number, full_name, program, fee_balance)
VALUES
('LGU2026-002', 'Mutinta Habeenzu', 'LLB', 7200.00),
('LGU2026-003', 'Bwalya Kunda', 'BBA', 4500.00),
('LGU2026-004', 'Thandiwe Phiri', 'BSc Computing', 6100.00);

Notice we never mention id or created_at โ€” AUTO_INCREMENT and DEFAULT fill them automatically. Text values go in single quotes; numbers don't.

SELECT โ€” reading rows (the command you'll use most)

-- Everything from the drawer ( * means "all columns")
SELECT * FROM students;

-- Only some columns
SELECT full_name, program FROM students;

-- Filtering with WHERE
SELECT * FROM students WHERE program = 'BSc Computing';

-- Comparison and combining conditions
SELECT * FROM students WHERE fee_balance > 5000 AND program = 'LLB';

-- Pattern search: names containing "anda" anywhere (% = "anything here")
SELECT * FROM students WHERE full_name LIKE '%anda%';

-- Sorting: highest balance first
SELECT * FROM students ORDER BY fee_balance DESC;

-- Only the first 2 rows
SELECT * FROM students ORDER BY created_at DESC LIMIT 2;

Result of the first query โ€” this shape (rows ร— columns) is what PHP will receive in the next chapter:

id | student_number | full_name | program | fee_balance 1 | LGU2026-001 | Chanda Mwila | BSc Computing | 5000.00 2 | LGU2026-002 | Mutinta Habeenzu | LLB | 7200.00 3 | LGU2026-003 | Bwalya Kunda | BBA | 4500.00 4 | LGU2026-004 | Thandiwe Phiri | BSc Computing | 6100.00

UPDATE โ€” changing rows

UPDATE students
SET fee_balance = 3500.00
WHERE id = 1;
โš ๏ธ The most expensive mistake in SQL

Forget the WHERE clause and every single row is updated. UPDATE students SET fee_balance = 0; just made the whole university free. The same danger applies to DELETE. Ritual to adopt for life: write the WHERE first, then go back and write the rest.

DELETE โ€” removing rows

DELETE FROM students WHERE id = 4;

Two tables and the idea of relationships

Real systems have many drawers that reference each other. A courses table, and a marks table that links students to courses:

CREATE TABLE courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    code VARCHAR(10) NOT NULL UNIQUE,
    title VARCHAR(100) NOT NULL
);

CREATE TABLE marks (
    id INT AUTO_INCREMENT PRIMARY KEY,
    student_id INT NOT NULL,
    course_id INT NOT NULL,
    score INT NOT NULL,
    FOREIGN KEY (student_id) REFERENCES students(id),
    FOREIGN KEY (course_id) REFERENCES courses(id)
);

A foreign key is a column that holds another table's id โ€” a "see drawer S, card 3" note. It links the drawers together and MySQL refuses marks pointing at students who don't exist. To read linked data back in one combined result, SQL offers JOIN:

SELECT s.full_name, c.code, m.score
FROM marks m
JOIN students s ON s.id = m.student_id
JOIN courses  c ON c.id = m.course_id;
full_name | code | score Chanda Mwila | COMP101 | 82 Mutinta Habeenzu | COMP101 | 67

Don't worry about mastering JOINs today โ€” our project uses a single table, and you can return to JOINs once the basics feel comfortable. Just remember: ids link tables together.

โœ๏ธ Try it yourself

In phpMyAdmin's SQL tab: (1) create the school_db database and students table from this chapter, (2) insert the four students, (3) write a SELECT that shows only BSc Computing students ordered by fee_balance, highest first.

Show the query for step 3
SELECT * FROM students
WHERE program = 'BSc Computing'
ORDER BY fee_balance DESC;
4 | LGU2026-004 | Thandiwe Phiri | BSc Computing | 6100.00 1 | LGU2026-001 | Chanda Mwila | BSc Computing | 5000.00
Quick quiz

Which SQL command reads data from a table?

Quick quiz

What does DELETE FROM students; (no WHERE) do?

Quick quiz

Which column type should store money?

๐Ÿ”‘ Key points
  • Database = filing cabinet, table = drawer, row = record card, column = labelled blank.
  • Every table starts with id INT AUTO_INCREMENT PRIMARY KEY.
  • The CRUD four: INSERT (create), SELECT (read), UPDATE (update), DELETE (delete).
  • WHERE filters; forgetting it on UPDATE/DELETE affects every row. Write WHERE first!
  • ORDER BY ... DESC sorts; LIKE '%x%' pattern-searches; LIMIT caps the rows.
  • Use DECIMAL for money. Foreign keys (ids) link tables; JOIN reads them together.