Course topics

By WebNest Studio Engineering Team

Database and SQL Tutorial

The Relational Model

The relational model, introduced by E. F. Codd, represents all data as relations — what SQL calls tables. Every relational database, regardless of vendor, is built on this same mathematical foundation, which is why SQL concepts transfer cleanly between PostgreSQL, MySQL, and other systems.

Understanding the relational model as "sets of tuples," rather than just "tables that look like spreadsheets," explains why SQL behaves the way it does: why row order is not guaranteed unless you explicitly sort, why duplicate rows are technically allowed but usually avoided, and why joining tables is a first-class, efficient operation rather than a workaround.

Why it matters

SQL works on whole sets of rows at once, not on one row at a time. People coming from programming languages reach for loops and are surprised that rows have no fixed order. Thinking in sets is the shift that makes SQL feel natural, and it is why one short statement can update a million rows.

Relations, Tuples, and Attributes

In relational theory, a "relation" is a table, a "tuple" is a row, and an "attribute" is a column. Formally, a relation is a set of tuples that all share the same attributes (columns) and types. This is why every row in a SQL table must have a value (or NULL) for every defined column — the structure is uniform by definition, unlike a loosely structured document format.

Set-Based Thinking

SQL is fundamentally set-based, not row-by-row like traditional procedural code. A query such as SELECT * FROM orders WHERE total > 100 describes the set of rows you want, not a loop that inspects rows one at a time. The database engine decides how to actually retrieve that set efficiently. This is a mental shift for programmers used to for-loops: instead of writing "for each row, check the condition," you describe the condition and let the engine figure out the best access path.

No Guaranteed Order Without ORDER BY

Because a relation is mathematically a set (or in SQL's practical implementation, a multiset that allows duplicates), there is no inherent row order. A query without an explicit ORDER BY clause may return rows in any order the engine finds convenient, and that order can change between runs, even without any data changes. Relying on unspecified order is one of the most common relational-model misunderstandings among beginners.

Example

The same logical relation, queried as a set rather than iterated row by row

SQL
SELECT name, department
FROM employees
WHERE department = 'Engineering'
ORDER BY name;
Output
Returns 2 rows, ordered by name: ('Asha Rao', 'Engineering'), ('Meera Iyer', 'Engineering')

Common Mistakes

  • Assuming SELECT results come back in insertion order or "table order" — without ORDER BY, order is not guaranteed.
  • Writing SQL like a procedural loop ("for each customer, then check...") instead of expressing the desired result set directly.
  • Confusing a relation (a table definition with columns and types) with a specific set of rows currently stored in it — the structure and the data are different concepts.

Exercise

The rows were inserted in the order Zoya, Asha, Ravi. A table has no guaranteed order, so write a query that returns the names in alphabetical order explicitly. Then raise every salary by 1000 with a single statement, and return the total of all salaries as total.

Expected output: name, Asha, Ravi, Zoya, total, 153000 (one per line)

SQL · starter code
CREATE TABLE staff (id INTEGER PRIMARY KEY, name TEXT, salary INTEGER);
INSERT INTO staff (id, name, salary) VALUES (1, 'Zoya', 60000), (2, 'Asha', 50000), (3, 'Ravi', 40000);

-- TODO: the names in alphabetical order

-- TODO: one statement that raises every salary by 1000

-- TODO: the sum of all salaries as "total"
Show hints
  • Order is requested with ORDER BY name.
  • An UPDATE with no WHERE clause applies to every row: SET salary = salary + 1000.
Show solution
SQL · solution
CREATE TABLE staff (id INTEGER PRIMARY KEY, name TEXT, salary INTEGER);
INSERT INTO staff (id, name, salary) VALUES (1, 'Zoya', 60000), (2, 'Asha', 50000), (3, 'Ravi', 40000);

SELECT name FROM staff ORDER BY name;

UPDATE staff SET salary = salary + 1000;

SELECT SUM(salary) AS total FROM staff;

Quick quiz

1. In the relational model, what is a "relation"?

  • A. A link between two tables
  • B. A foreign key
  • C. A table
  • D. A query
Show answer

C. A relation is a table, a tuple is a row, and an attribute is a column.

2. In what order does SELECT * FROM users; return rows?

  • A. Always in insertion order
  • B. No order is guaranteed without ORDER BY
  • C. Always sorted by id
  • D. Alphabetical order
Show answer

B. The database may return rows in whatever order is cheapest, and that can change.

3. How do you give every product a 10% price increase?

  • A. Loop over the rows in the application and update each one
  • B. Run one INSERT per product
  • C. It cannot be done in SQL
  • D. One UPDATE statement that sets price = price * 1.10
Show answer

D. SQL statements operate on the whole set of matching rows.

Interview questions

What does it mean that SQL is declarative?

Show answer

In a declarative language you state what result you want, not the steps to compute it. A query says which rows and columns are needed; the database's query planner decides how to get them: which indexes to use, in which order to join tables, and so on. This is why the same query can become faster after an index is added, with no change to the SQL.

What is set-based thinking in SQL?

Show answer

It means expressing an operation as something done to a whole set of rows at once, instead of processing rows one by one in a loop. An UPDATE with a WHERE clause, or a join between two tables, describes all the affected rows in one statement. Set-based statements are shorter and much faster than row-by-row processing, because the database can optimise the whole operation.

Key Points to Remember

  • A relation is a table, a tuple is a row, and an attribute is a column — the same relational vocabulary underlies every relational database.
  • SQL is set-based: queries describe the result set, not a step-by-step retrieval procedure.
  • Row order is never guaranteed unless an ORDER BY clause is used explicitly.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs your SQL on SQLite in your browser. Standard SQL works; a few features that exist only in PostgreSQL or MySQL do not. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

These examples need a project environment on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering