SELECT is the verb SQL uses for reading: it lists what you want, says where the rows come from, and hands back a table. A statement is a few hard-ordered clauses, a semicolon, and case-insensitive keywords — and the two mistakes almost everyone makes first have receipts below.
What does a complete SELECT statement look like?
Take a small tool shop table as today's subject. Six rows are enough to see every shape a result can take; the -- weight grams comment is plain text to the engine, purely for the human reader.
CREATE TABLE tools (
id INTEGER PRIMARY KEY,
name TEXT,
weight REAL, -- grams, as sold
price REAL,
stock INTEGER
);
INSERT INTO tools (name, weight, price, stock) VALUES
('Ball-peen hammer', 480, 17.90, 22),
('Torpedo level', 210, 12.60, 15),
('Pliers set', 640, 24.30, 11),
('Chalk line', 95, 8.95, 30),
('Caulking gun', 380, 11.20, 18),
('Wire strippers', 150, 9.40, 26);
Around that data, the plainest readable query in the language runs and answers with everything, borrowing the same * shorthand you saw for a full dump:
SELECT * FROM tools;
id name weight price stock
-- ---------------- ------ ----- -----
1 Ball-peen hammer 480.0 17.9 22
2 Torpedo level 210.0 12.6 15
3 Pliers set 640.0 24.3 11
4 Chalk line 95.0 8.95 30
5 Caulking gun 380.0 11.2 18
6 Wire strippers 150.0 9.4 26
Read the statement in the order the engine does: SELECT names the columns to project, FROM names the table to read, and the ; says the statement is complete. Those two clause positions are fixed — swapping the clause order is always an error, while keyword case is never one:
select name, stock from tools where stock >= 26;
name stock
-------------- -----
Chalk line 30
Wire strippers 26
Lowercase keywords, mixed case table names, one query — one result. Conventional style keeps keywords in capitals so the eye can find verbs quickly; that is taste and agreement, not grammar. The comparison >= filtered six rows down to two; Module 2 dissects filters clause by clause, so treat this one as a preview that computing from a table can apply conditions too.
How do you ask for exactly the columns you need?
Real reports almost never want everything. Name the columns and the engine projects just them — order given, order returned:
SELECT name, weight FROM tools;
name weight
---------------- ------
Ball-peen hammer 480.0
Torpedo level 210.0
Pliers set 640.0
Chalk line 95.0
Caulking gun 380.0
Wire strippers 150.0
Every SELECT produces a brand new result table; the tools table itself never changed. That read-only character is what makes SELECT safe to run all day in production — the worst outcome is a slow report, not a lost row. You are free to list columns in any order, too — analytics browses love reversed order, showing counts before labels:
SELECT stock, price, name FROM tools LIMIT 3;
stock price name
----- ----- ----------------
22 17.9 Ball-peen hammer
15 12.6 Torpedo level
11 24.3 Pliers set
LIMIT 3 kept the demo short — lesson 9 gives it a full treatment. The important habit to build now: your projected order rules your output order, so pick it consciously.
What errors ambush most beginners in the first hour?
Two stand out, and both fail in misleadingly quiet ways. The first is a forgotten comma: put a space where the comma belongs and the engine assumes you named a column alias — name price quietly becomes the name column, renamed price:
SELECT name price
FROM tools;
price
----------------
Ball-peen hammer
Torpedo level
Pliers set
Chalk line
Caulking gun
Wire strippers
Notice the header: the engine did not fetch a missing price column — it renamed name to price. One missing comma, and the report lies. Lesson 4 explains aliases in full precisely because that trap behaves like a feature.
The second error is the semicolon. A single statement without one still runs, because the shell reads to the end of the input. Two statements, and the first one without a terminator hits the second and the engine gives up:
Parse error near line 1: near "SELECT": syntax error
SELECT id FROM tools SELECT name FROM tools
^--- error here
End every statement with a semicolon and both failure modes vanish. Interactive SQL editors in web consoles, MySQL Workbench and PostgreSQL psql all read one statement at a time the same way, so the habit transfers intact.
How do you catch these two mistakes early?
Read queries aloud using the engine's order — select these columns, from this table — then run the smallest version first. A trick that works surprisingly well: delete half of your query, run it, confirm it works, restore one clause at a time. The alias trap announces itself in the output header, so glance at headers before celebrating data; the semicolon trap announces itself only when statements stack, so make one statement the unit of work forever.
Quick reference
- A SELECT has SELECT, then FROM, then optionally more clauses, ending in a semicolon.
- Keywords are case-insensitive; capitalise by convention so structure stays visible.
- SELECT without a FROM-listed change can read but never modify — reads are safe to repeat.
- A missing comma silently renames a column; a missing semicolon should fail loudly when more statements follow.
Practice: write three queries against tools: one projecting every column, one projecting only name and price, and — deliberately — one with a missing comma so the header shows the alias effect. Re-run the two-statement parse error and match the engine's offending position marker against your own statement.