What is a relational database and SQL: an explanation for beginners
An e-shop needs to reliably connect customers, orders, products and payments. A relational database stores this data in clear tables and guards the relationships between them. Using the SQL language we then read, filter, join and change the data. We will show everything on a small database of orders that you can create with no prior knowledge.
SQL in one example
Imagine a table zakaznici (customers). The question “What are the names and e-mails of all customers?” is written like this:
SELECT jmeno, email
FROM zakaznici;
| jmeno | |
|---|---|
| Jana Nováková | jana@example.cz |
| Petr Svoboda | petr@example.cz |
SELECT says which columns we want to see, and FROM which table the database should take them from. You don’t need to know anything else yet — you will run the same query yourself later.
What a database is
A database is an organised collection of data that a computer can work with efficiently. It is not just a file on disk. A database system also takes care of searching, concurrent work by several people, rule checking, permissions, backup and recovery after an error.
A database can hold e-shop customers, account transactions, measurement results, stock levels or hotel reservations. They have one thing in common: the data changes continuously and must stay correct even when several users work with it at once.
The program that stores and processes the data is simply called a database system. These include, for example, PostgreSQL, MySQL and SQLite. You don’t need to choose between them to begin with — first we learn the principles they share.
Why it is called relational
Relational means the tables are not isolated. They are connected via shared values: an order, for example, carries the identifier of the customer it belongs to.
The advantage of this split is simple: you store the customer’s name and e-mail only once. Each of their orders then contains only a reference to the customer. When the e-mail changes, you fix one row instead of dozens of orders. This limits duplication and the risk that different copies start to contradict each other.
Tables, rows and columns
Table
Groups records of the same type, for example customers. Every table has a name and a predefined structure.
Row
Represents one specific record: one customer, one order or one product.
Column
Describes one property of a record, such as e-mail, price or creation date.
Every column has a data type. A name is usually text, a count an integer, and a date has its own type in many databases. Data types prevent nonsense: the text “several” shouldn’t get into a column holding a quantity.
The overview of tables, columns and relationships is called the database schema. For your first queries, though, it is enough to remember the trio: a table contains rows and every row has columns.
Keys and relationships between tables
Primary key: unique identity
Every row should have a value that identifies it unambiguously. That is usually the primary key (PRIMARY KEY), often a numeric id column. Two customers can have the same name, but they cannot have the same ID.
Foreign key: a guarded reference
A foreign key (FOREIGN KEY) refers to the primary key of another table. The column objednavky.zakaznik_id may thus contain only the ID of a customer who really exists. Thanks to this the database won’t allow an “orphan” order without a customer.
Our example uses a 1:N relationship: one customer can have several orders. Later you will also meet the 1:1 relationship and the M:N relationship, which is handled with a junction table. You don’t need to know them for your first database, though.
A database can guard other rules too: NOT NULL requires a value, UNIQUE forbids duplicates and CHECK verifies a condition, for example that the price is not negative.
What SQL is
SQL stands for Structured Query Language. SQL doesn’t describe a step-by-step procedure like an ordinary programming language. With it you mainly say what result you want and the database itself chooses how to get it.
For example the sentence “find orders more expensive than CZK 1,000 and sort them from newest” maps directly onto a query with SELECT, WHERE and ORDER BY. To start, four commands are enough:
CREATE TABLEcreates a table.INSERTadds new rows.SELECTreads data.UPDATEandDELETEchange or delete data.
Your first database step by step
We will create two tables from our e-shop. The examples are prepared for SQLite, which needs no server and stores the whole database in a single file.
PRAGMA foreign_keys = ON;
CREATE TABLE zakaznici (
id INTEGER PRIMARY KEY,
jmeno TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
);
CREATE TABLE objednavky (
id INTEGER PRIMARY KEY,
zakaznik_id INTEGER NOT NULL,
cena_kc INTEGER NOT NULL CHECK (cena_kc >= 0),
vytvoreno TEXT NOT NULL,
FOREIGN KEY (zakaznik_id) REFERENCES zakaznici(id)
);
The first line turns on foreign key checking in SQLite. For simplicity the price is an integer in Czech crowns and we store the date as text in the format YYYY-MM-DD. Other database systems offer specialised types for money and dates. Now we insert a few rows:
INSERT INTO zakaznici (id, jmeno, email) VALUES
(1, 'Jana Nováková', 'jana@example.cz'),
(2, 'Petr Svoboda', 'petr@example.cz');
INSERT INTO objednavky (id, zakaznik_id, cena_kc, vytvoreno) VALUES
(101, 1, 1290, '2026-08-10'),
(102, 1, 490, '2026-08-12'),
(103, 2, 2150, '2026-08-13');
Text values are in single quotes; numbers need no quotes.
How to read data with SELECT
You already know the most used command, SELECT, from the opening example. The asterisk in SELECT * means “all columns”. It is convenient for first experiments, but in a normal application it is better to name the columns. The query is more readable and doesn’t transfer data you don’t need.
Filtering, sorting and limiting the number of results
SELECT id, cena_kc, vytvoreno
FROM objednavky
WHERE cena_kc >= 1000
ORDER BY vytvoreno DESC
LIMIT 5;
| id | cena_kc | vytvoreno |
|---|---|---|
| 103 | 2 150 | 2026-08-13 |
| 101 | 1 290 | 2026-08-10 |
WHERE keeps only the rows that meet the condition. ORDER BY ... DESC sorts from the highest value, so for a date from the newest. LIMIT 5 returns at most five records.
Filter a missing value with IS NULL or IS NOT NULL, not with = NULL. NULL means the value is missing or unknown; it is neither zero nor an empty string.
How to join tables with JOIN
In the orders we only have zakaznik_id. The name is in the customers table. The JOIN command joins both tables according to the condition after ON:
SELECT
z.jmeno,
o.cena_kc,
o.vytvoreno
FROM zakaznici AS z
JOIN objednavky AS o
ON o.zakaznik_id = z.id
ORDER BY o.vytvoreno DESC;
| jmeno | cena_kc | vytvoreno |
|---|---|---|
| Petr Svoboda | 2 150 | 2026-08-13 |
| Jana Nováková | 490 | 2026-08-12 |
| Jana Nováková | 1 290 | 2026-08-10 |
The abbreviations z and o are table aliases. Thanks to them the query stays short, but it is still clear which table each column comes from.
When we want a summary per customer, we add aggregate functions and grouping:
SELECT
z.jmeno,
COUNT(o.id) AS pocet_objednavek,
SUM(o.cena_kc) AS celkem_kc
FROM zakaznici AS z
JOIN objednavky AS o
ON o.zakaznik_id = z.id
GROUP BY z.id, z.jmeno
ORDER BY celkem_kc DESC;
COUNT counts rows, SUM adds up prices and GROUP BY specifies that the calculation is done separately for each customer. Jana has two orders for CZK 1,780, Petr one for CZK 2,150.
How to change data safely
New rows are added by INSERT. Existing ones are changed by UPDATE and deleted by DELETE. For the last two commands the most important thing is the WHERE condition:
UPDATE zakaznici
SET email = 'jana.novakova@example.cz'
WHERE id = 1;
DELETE FROM objednavky
WHERE id = 102;
Without WHERE you can change everything
UPDATE zakaznici SET email = ... without a condition overwrites the e-mail of every customer. Likewise DELETE FROM objednavky deletes all orders. Before a change, first verify the same condition with SELECT.
Several related changes belong in a transaction. It guarantees that either all of them are performed or none. On success, COMMIT confirms the changes; on a problem, ROLLBACK reverts them. Thanks to this you won’t, for example, deduct money from one account without it being credited to the other.
Relational database vs. Excel and NoSQL
| Tool | Suited to | Starts to be weak when |
|---|---|---|
| Excel / spreadsheet | Quick calculations, small overviews, manual analysis | Several people change the data, you need relationships and exact rules |
| Relational database | Data with a clear structure, exact rules, reports and connected records | The structure changes often or the main questions concern long paths in a network of relationships |
| NoSQL database | Documents, key–value, very flexible data or specialised tasks | You need many firm relationships, exact transactions and tabular reports |
Excel is not a “bad database” — it is a different tool. For a personal list or a one-off analysis it tends to be faster. A relational database wins the moment data feeds an application, must follow rules and is used by several processes at once.
NoSQL is neither a single technology nor automatically a more modern replacement for SQL. It includes document, key–value, column and graph databases. Each solves a different type of problem. If you are interested in a model focused on paths and a network of relationships, also read the article What is a graph database and how AI agents use it.
Common beginner mistakes
- Everything in one table. Repeating customer details on every order leads to duplicates. Separate entities and connect them with keys.
- No primary key. Without a unique ID, records are hard to change, reference and distinguish.
- Numbers and dates stored as text. The text “100” may sort before “20” and the date “1 Sep 2026” is hard to compare. Use the right types.
- Confusing NULL, zero and an empty string. Each of these values means something different and the database also computes with them differently.
- UPDATE or DELETE without WHERE. First run a SELECT with the same condition and verify the affected rows.
- Assembling SQL from user text. In an application, never paste input directly into a query. Use parameterised queries — they protect against SQL injection.
- A database without backups. Foreign keys protect relationships, not against an administrator’s mistake, a disk failure or an application bug.
How to try SQL in 20 minutes
For first experiments you need no server. The simplest is SQLite: the whole database can be a single file and you can run SQL in the free program DB Browser for SQLite. Without installing anything, the interactive lessons of SQLBolt will do.
Create the tables
Copy the first block with CREATE TABLE and run it.
Insert the sample data
Run both INSERT commands and check the tables with SELECT * FROM zakaznici;.
Ask the database your own question
Find orders over CZK 1,000, change the sort order and add another customer.
Try a JOIN
List the customer’s name for every order. Then change the query so that it shows only Jana.
Key takeaways
- A relational database stores structured data in tables and connects them with keys.
- A primary key uniquely identifies a row; a foreign key guards a reference to another table.
- SQL is a language for defining, reading and changing data — it is not a specific database product.
SELECTreads data,WHEREfilters,ORDER BYsorts andJOINconnects tables.- Correct data types, constraints, transactions, parameterised queries and backups protect data against common mistakes.
Want to learn SQL and working with data hands-on?
In the Relational Databases and SQL course you practise table design, relationships and SQL queries from the basics to more advanced data work. If you want to combine SQL with Python, visualisation and machine learning, the Data Analysis and Artificial Intelligence course follows on.
Sources and further reading
- PostgreSQL Tutorial — official introduction to relational databases and SQL
- SQLite SQL Language — overview of the SQL supported in SQLite
- SQLBolt — short interactive exercises in the browser
- OWASP: SQL Injection — why applications use parameterised queries