Introduction to SELECT Queries: Data Retrieval in PostgreSQL
Master the SQL SELECT statement. Learn how to query entire tables, target specific columns, and interpret result sets in your PostgreSQL database.

Previously in this course, we covered the Introduction to the Relational Model: Why PostgreSQL Wins and completed the necessary setup to create our store database and define our products table. Now that your schema is in place, it’s time to see what’s inside.
In this lesson, we explore the SELECT statement, the cornerstone of all data retrieval. You will learn how to pull the entire contents of your inventory and how to refine your requests to get exactly the data you need, nothing more.
The Foundation of Data Retrieval: The SELECT Statement
The SELECT statement is how we ask the database to return records. In PostgreSQL, a query typically follows a simple structure: you specify the columns you want, then specify the source table.
Think of the database as a highly organized filing cabinet. The SELECT statement is the instruction slip you hand to the clerk, telling them exactly which folders (tables) and which documents (columns) to pull for you.
Executing a SELECT * Query
When you are first exploring a table, you often want to see everything. The asterisk (*) is a wildcard character that tells PostgreSQL, "Return every column defined in this table."
To view your entire products table, run this in your psql terminal or pgAdmin query tool:
SQLSELECT * FROM products;
This query returns a result set—a tabular representation of the data currently stored in your table. If you just created the table, this might return an empty set, which is perfectly normal. As we move into later lessons involving data insertion, this command will become your primary way of verifying your work.
Targeting Specific Columns
While SELECT * is convenient for discovery, it is considered bad practice in production applications. Requesting columns you don't need increases network traffic and memory usage on the database server.
Instead, list the specific columns you need by separating them with commas. For our store inventory, you might only care about the name and the current price:
SQLSELECT name, price FROM products;
By explicitly naming your columns, you make your code more resilient. If you later add a description or supplier_id column to your products table, your existing queries won't suddenly start returning extra, unwanted data.
Understanding Result Sets

When you execute a query, PostgreSQL returns a result set. It is helpful to view this as a temporary, read-only table generated on the fly.
Key attributes of a result set include:
- Order: By default, rows are returned in an undefined order unless you explicitly define one (which we will cover in a future lesson).
- Metadata: The result set includes headers that mirror your table's column names.
- Datatypes: Each column in the result set retains the type defined in your
CREATE TABLEstatement.
Hands-on Exercise: Inspecting Your Inventory
Since we have already defined our products table in our previous design lesson, let's practice retrieving data from it.
- Open your terminal and connect to your store database.
- Run
SELECT * FROM products;to observe the structure. - Write a new query that only retrieves the
idandnamecolumns. - Verify the output. Notice how the database ignores the other columns like
priceorstock_quantity.
Common Pitfalls
- Forgetting the Semicolon: PostgreSQL requires a semicolon (
;) to terminate a query. If you press Enter and nothing happens, your terminal is likely waiting for that semicolon to know the command is complete. - Over-fetching with
SELECT *: While tempting during development, always aim to select only the columns you need. It prevents "hidden" bugs where your application logic might break if a table schema changes unexpectedly. - Case Sensitivity: While SQL keywords like
SELECTandFROMare case-insensitive, identifiers (like table and column names) can be case-sensitive if they were created with double quotes. Stick tosnake_casewithout quotes to keep things simple.
FAQ
Why does my SELECT query return an empty result?
If your table exists but has no data, SELECT will return an empty result set. This just means you haven't performed an INSERT yet.
Does SELECT change the data in my database?
No. SELECT is a read-only operation. It creates a view of the current data but does not modify, delete, or add any rows.
Can I rename columns in the result set?
Yes, you can use the AS keyword (e.g., SELECT name AS product_name FROM products;), which we will explore in detail as we progress.
Recap

In this lesson, we moved from designing our schema to interacting with our data. You learned that SELECT * is the "everything" wildcard, but explicit column selection is the professional standard for performance and stability. You now understand that result sets are the temporary, tabular outputs of your queries.
Up next: We will begin narrowing down our data by learning to use the WHERE clause to filter rows based on specific conditions.
Work with me

Laravel SaaS MVP & Multi-Tenant App Development
Launch your SaaS MVP on Laravel — multi-tenant, subscription-ready, and built by the engineer behind a platform serving 10,000+ paying users.

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.

