New: Try Voli The Bear, Fast package manager (and not only) for Windows

Try it in Practice →

Updated Jul 10, 2026 Edit on GitHub

Asking for Data: SELECT ... FROM

A database is, at heart, a set of tables - and a table is just a grid: columns across the top (the kinds of things you store), rows going down (one row per actual thing). A query is you pointing at that grid and saying "give me these columns, from that table." Master that one sentence and you've got the spine of every SELECT you'll ever write.

Let's meet the table we'll use for the whole guide. Picture a users table like this:

 id │ name           │ email                 │ city        │ age │ created_at
────┼────────────────┼───────────────────────┼─────────────┼─────┼────────────
  1 │ Ada Lovelace   │ [email protected]       │ London      │  36 │ 2026-01-04
  2 │ Grace Hopper   │ [email protected]     │ New York    │  41 │ 2026-01-09
  3 │ Alan Turing    │ [email protected]      │ London      │  29 │ 2026-02-15
  4 │ Katherine J.   │ [email protected]       │ Hampton     │  52 │ 2026-03-01
  5 │ Linus T.       │ [email protected]     │ Portland    │  33 │ 2026-03-22

📝 Terminology. A column is one labeled slot every row has (name, age). A row (also called a record) is one complete entry - one user. A table is the whole grid. When you query, you choose which columns you want back and the database hands you matching rows.

The query shape: SELECT ... FROM ...

What it actually is. A SELECT query is a request with two essential parts: what you want (the columns) and where it lives (the table). You read it almost like English: "SELECT name, email FROM users" means "get me the name and email columns, from the users table."

What it does in real life. The database finds the table, walks its rows, and returns a fresh grid containing only the columns you asked for. It doesn't change anything - SELECT only reads. You can run it as many times as you like with zero risk.

A real example.

SELECT name, email
FROM users;
 name           │ email
────────────────┼───────────────────────
 Ada Lovelace   │ [email protected]
 Grace Hopper   │ [email protected]
 Alan Turing    │ [email protected]
 Katherine J.   │ [email protected]
 Linus T.       │ [email protected]

What just happened: You asked for two columns, name and email, from users. The database gave back every row, but only those two columns - the id, city, age, and created_at values are still in the table, you just didn't ask for them, so they're not in the result. The result you get back is itself a little grid: this rows-and-columns answer is called the result set.

📝 Terminology. The grid a query returns is the result set - a temporary table of rows that matched, built just to answer your question. It vanishes once you've read it; it doesn't live in the database.

The semicolon ; at the end marks where your statement finishes. Some tools require it, others are forgiving - it's a good habit to always include it, especially once you start running several statements at once.

Picking columns vs. grabbing everything with *

What it actually is. The * (say "star") is a shortcut meaning "every column in this table." Instead of listing column names, you let the database fill them all in for you.

What it does in real life. SELECT * returns every column for the matching rows - handy when you're exploring a table and want to see what's even in there.

A real example.

SELECT *
FROM users;
 id │ name           │ email                 │ city        │ age │ created_at
────┼────────────────┼───────────────────────┼─────────────┼─────┼────────────
  1 │ Ada Lovelace   │ [email protected]       │ London      │  36 │ 2026-01-04
  2 │ Grace Hopper   │ [email protected]     │ New York    │  41 │ 2026-01-09
  3 │ Alan Turing    │ [email protected]      │ London      │  29 │ 2026-02-15
  4 │ Katherine J.   │ [email protected]       │ Hampton     │  52 │ 2026-03-01
  5 │ Linus T.       │ [email protected]     │ Portland    │  33 │ 2026-03-22

What just happened: The * told the database "don't make me name them - give me all the columns." You got the entire table back, every column, every row. Same rows as before; you just widened what came back.

⚠️ Gotcha. SELECT * is great for poking around by hand, but reach for named columns in real code (an app, a script, a saved report). Two reasons that bite later: (1) it pulls back columns you don't need, including possibly large or sensitive ones, which is wasteful; and (2) if someone later adds or reorders columns in the table, code that relied on SELECT * and the old column order can quietly break. Naming the columns you want is a small act of kindness to future-you.

💡 Key point. Every SELECT answers the question "which columns, from which table?" List the columns to be precise, or use * to grab them all while exploring. Either way, you get back a result set - a grid of rows - and the underlying table is untouched.

Try the shape yourself on a tiny built-in authors table:

SELECT name, country
FROM authors;

What just happened: You asked for two columns, name and country, from authors, and got every row back - but only those two columns. The id is still in the table; you just didn't ask for it.

Reading the result set

When a query comes back, read it the same way every time: the header row at the top tells you which columns you got and in what order; each row underneath is one matching record. If your SELECT listed columns in a particular order, the result honors that order - SELECT email, name puts email first, even though it sits second in the table. The database gives you the columns in the order you asked, not the order they're stored.

SELECT email, name
FROM users;
 email                 │ name
───────────────────────┼────────────────
 [email protected]       │ Ada Lovelace
 [email protected]     │ Grace Hopper
 [email protected]      │ Alan Turing
 [email protected]       │ Katherine J.
 [email protected]     │ Linus T.

What just happened: Same data, same rows - but because you wrote email first in the SELECT, the result set leads with email. The order of names in your SELECT list controls the order of columns in the answer.

One thing you've surely noticed: every example so far returned all five rows. That's because we haven't told the database to narrow things down yet. Asking for "all the rows" is fine on a five-row table; on a table with millions of rows, you'll want to filter. That's exactly what the next phase is about.

Recap

  1. A query asks "which columns, from which table?" - that's the SELECT ... FROM shape.
  2. SELECT name, email FROM users; returns only the columns you name, for every row.
  3. SELECT * returns every column - perfect for exploring, but name your columns in real code.
  4. What comes back is a result set: a temporary grid of rows. SELECT only reads; it never changes the table.
  5. The column order in your result follows the order you listed them in the SELECT.

You can now ask any table for any of its columns. Next, you'll learn to ask for only the rows you care about - by far the most useful skill in everyday SQL.


← Guide overview · Phase 2: Filtering & Sorting →

Before the quiz: without looking back, say (or jot down) the core idea of this phase in your own words.

Check your understanding 3 questions

1. What two essential parts does a SELECT query have?

2. What does `SELECT *` return, and when should you avoid it in real code?

3. What is the result set of a query?