SQL Introduction
What SQL is, the relational model, and the users/orders/products schema used throughout this section.
What SQL is
SQL (Structured Query Language) is the language used to define, query, and manipulate data stored in a relational database. Every mainstream relational database — MySQL, PostgreSQL, SQL Server, Oracle, SQLite — implements SQL, with a shared core syntax and vendor-specific extensions layered on top. Learning SQL well means learning that shared core first; the vendor-specific tutorials later in this track build on exactly what you learn here.
SQL splits into a few functional groups, though in everyday use most people just call all of it "SQL":
- DDL (Data Definition Language) —
CREATE,ALTER,DROP. Defines the structure of the database itself. - DML (Data Manipulation Language) —
SELECT,INSERT,UPDATE,DELETE. Reads and writes the data. - DCL (Data Control Language) —
GRANT,REVOKE. Controls permissions. - TCL (Transaction Control Language) —
COMMIT,ROLLBACK. Controls transaction boundaries.
The relational model
A relational database organizes data into tables (also called relations). Each table has a fixed set of columns (attributes, each with a data type) and holds any number of rows (records, each one instance of that structure).
The power of the relational model isn't any single table — it's that tables reference each other through shared key values, so data doesn't need to be duplicated everywhere it's needed. A users table holds user data once; an orders table refers back to a user by id rather than repeating that user's name and email on every order row.
Two kinds of keys make this work:
- A primary key uniquely identifies a row within its own table (no two rows share one, and it's never null).
- A foreign key is a column in one table that refers to a primary key in another, creating an enforced link between the two.
The schema used throughout this section
The rest of the SQL pages in this track query a small, consistent schema: users who place orders for products. Run this once and every later example refers back to it.
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
country VARCHAR(2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(150) NOT NULL,
category VARCHAR(50),
price DECIMAL(10,2) NOT NULL,
stock INT NOT NULL DEFAULT 0
);
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
order_date DATE NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);
A few things worth noticing in that definition:
id INT PRIMARY KEY AUTO_INCREMENT— the database assigns a unique, ever-increasing id automatically; you never supply it on insert.NOT NULLonnameandemailmeans those columns can never be left empty — the database rejects the insert instead of silently storing incomplete data.UNIQUEonemailprevents two users from registering with the same address, enforced by the database itself rather than trusted to application code.DECIMAL(10,2)forpricestores exact decimal values (up to 10 digits total, 2 after the point) — never use a floating-point type for money; the "MySQL" pages in this track cover exactly why.- The two
FOREIGN KEYconstraints mean anordersrow can never point at auser_idorproduct_idthat doesn't actually exist — the database enforces referential integrity for you.
With those three tables in place, inserting some data looks like this:
INSERT INTO users (name, email, country) VALUES
('Amara Diallo', 'amara@example.com', 'SN'),
('Liam Chen', 'liam@example.com', 'CA');
INSERT INTO products (name, category, price, stock) VALUES
('Wireless Mouse', 'Electronics', 24.99, 150),
('Mechanical Keyboard', 'Electronics', 89.00, 60);
INSERT INTO orders (user_id, product_id, quantity, status, order_date) VALUES
(1, 1, 2, 'shipped', '2026-01-15'),
(1, 2, 1, 'pending', '2026-02-03'),
(2, 2, 1, 'shipped', '2026-02-10');
Common mistakes
- Treating SQL keywords as case-sensitive syntax rules — they aren't (
selectandSELECTbehave identically), but writing keywords inUPPERCASEand identifiers inlowercaseis the near-universal convention that keeps queries readable. - Skipping
NOT NULLand foreign key constraints "to keep things simple," then relying on application code to enforce rules the database would enforce for free — and inevitably missing a code path that lets bad data in. - Using a floating-point type for money because it "seems like a number." Floating-point can't represent many decimal fractions exactly, which causes rounding errors that compound over many transactions.