Relational Databases and DBMS: Basics and Running MySQL
Picture a forum table where one cell holds “Cycling; Fishing”. How do you find everyone who started a thread about fishing when the values are glued together in a single string? This is exactly the kind of problem relational databases, and the systems that manage them, are designed to solve.
A database is an organized collection of related data stored in one or more files. A DBMS (database management system) is the software that creates the database, stores the data, runs queries and keeps the data consistent. In this lesson you will learn how relational databases work, then run MySQL and execute your first SQL query.
Database vs DBMS: What Is the Difference
A database is the data itself, while a DBMS is the program that works with it: the program does not keep the information “inside itself”, it manages the database files. A Java application never reads those files directly - it sends requests to the DBMS in SQL, and the DBMS returns the result.
| Term | What it is | Example |
|---|---|---|
| Database | A collection of related data organized according to a data model | Forum data: users, threads, posts |
| DBMS | Software that creates databases, stores data, runs queries and controls access | MySQL, PostgreSQL, Oracle Database |
| SQL | Structured Query Language: the language an application uses to read and write data | SELECT * FROM users; |
Examples of databases are everywhere: the product catalog and orders of an online store, bank accounts and payments, train timetables, forum users and their posts. Each of these databases is run by a DBMS.
The main functions of a DBMS are storing and searching data, executing SQL queries, enforcing data integrity (the data never breaks the rules defined for the tables), handling many users at the same time, managing access rights, and backup and recovery.
In the simplest case the flow looks like this: the application sends an SQL query to the DBMS, the DBMS reads or changes the database files and returns the result.

Types of DBMS with Examples
The type you will meet most often in software development is the relational DBMS (RDBMS), which stores data in tables: MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server and SQLite. Other data models are served by non-relational (NoSQL) systems.
| Type of DBMS | How it stores data | Examples |
|---|---|---|
| Relational | Tables with rows and columns, relationships between tables | MySQL, MariaDB, PostgreSQL, Oracle, SQL Server, SQLite |
| Document | Documents (usually JSON) | MongoDB |
| Key-value | “Key → value” pairs, usually in memory | Redis |
| Graph | Nodes and the relationships between them | Neo4j |
| Hierarchical and network | Tree-like and graph-like records; historical models that came before the relational one | IMS (hierarchical), IDMS (network) |
This module uses MySQL: it is free, widely used and a good fit for learning. Almost everything you learn about SQL here also works in other relational databases, with minor differences in dialect.
The Relational Model: Tables, Rows and Columns
A relational database stores data in two-dimensional tables: each row describes one record, and each column describes one attribute of that record. A table in a relational database has the following properties:
- every column has a unique name;
- all values in a column have the same type (number, string, date);
- there are no duplicate rows;
- the order of rows does not matter;
- each cell, at the intersection of a row and a column, holds a single atomic value, not a list of values.
“No duplicate rows” is a property of the model: a real SQL table without constraints will happily accept two identical rows, and it is the primary key that prevents this (keys are covered in a separate lesson of this module). The atomicity requirement is the foundation of normalization, which also has its own lesson in this module.
Example: the city table
Each row of the city table is one city, and each column is one of its attributes: name, country code, district and population.
| ID | Name | CountryCode | District | Population |
|---|---|---|---|---|
| 1 | Kabul | AFG | Kabol | 1,780,000 |
| 2 | Qandahar | AFG | Qandahar | 237,500 |
| 3 | Herat | AFG | Herat | 186,800 |
| 4 | Mazar-e-Sharif | AFG | Balkh | 127,800 |
| 5 | Amsterdam | NLD | Noord-Holland | 731,200 |
| 6 | Rotterdam | NLD | Zuid-Holland | 593,321 |
| 7 | Haag | NLD | Zuid-Holland | 440,900 |
| 8 | Utrecht | NLD | Utrecht | 234,323 |
| 9 | Eindhoven | NLD | Noord-Brabant | 201,843 |
| 10 | Tilburg | NLD | Noord-Brabant | 193,238 |
| 11 | Groningen | NLD | Groningen | 172,701 |
| 12 | Breda | NLD | Noord-Brabant | 160,398 |
Why Data Is Split into Tables: a Forum Example
Data is split across several tables so that every cell holds exactly one value and nothing is duplicated. Suppose you need to store forum users and the threads they started. With a single table, you get this:
| Name | Threads started | |
|---|---|---|
| Alice | [email protected] | Fishing |
| Bob | [email protected] | Cycling; Fishing |
| Carol | [email protected] | Board games |
Bob has two threads in one cell, which breaks atomicity: searching for the “Fishing” thread now means parsing strings. So the table is split in two:
| Name | |
|---|---|
| Alice | [email protected] |
| Bob | [email protected] |
| Carol | [email protected] |
| Title | Author |
|---|---|
| Fishing | Alice |
| Cycling | Bob |
| Fishing | Bob |
| Board games | Carol |
Now every cell holds a single value. What is left is to link rows of different tables reliably (for example, a thread and its author, even if a second user named Bob joins the forum) - relational databases use keys for this. How keys work is covered in a separate lesson of this module.
How to Run MySQL
There are two ways to run MySQL: in a Docker container (one command, nothing is left behind on your system) or by installing it on your computer. This course uses MySQL 8.4, a long-term support (LTS) release. Versions 5.7 and 8.0 have reached end of life (8.0 in April 2026), so do not learn on them.
Since 2026 MySQL has two LTS lines, 8.4 and 9.7, and new Innovation releases use calendar version numbers: 26.7, 26.10 and so on. For the queries in this module, there is no difference between them.
Option 1. Run MySQL in Docker
If Docker is already installed, MySQL starts with a single command:
docker run --name mysql-course -e MYSQL_ROOT_PASSWORD=secret -p 3306:3306 -v mysql_data:/var/lib/mysql -d mysql:8.4 | Part of the command | What it does |
|---|---|
--name mysql-course | The container name; you use it to start, stop and connect to the container |
-e MYSQL_ROOT_PASSWORD=secret | Sets the password of the root user; without this variable the container exits with an error right away |
-p 3306:3306 | Maps container port 3306 to port 3306 on your computer (format host_port:container_port) |
-v mysql_data:/var/lib/mysql | A named volume: the data lives outside the container and survives when the container is removed |
-d mysql:8.4 | Runs the container in the background from the MySQL 8.4 LTS image |
The first run downloads the image and initializes the database, which takes anywhere from a few seconds to a minute. The server is ready when the log shows ready for connections together with port: 3306: on the first run the same line is also printed for the temporary initialization server (with port: 0), and there is no point connecting to that one. Then check the version and connect with the client inside the container:
docker logs mysql-course
docker exec mysql-course mysql --version
docker exec -it mysql-course mysql -uroot -p Enter the password (secret) and you will see the mysql> prompt. Type exit to leave. You can stop and start the container again with docker stop mysql-course and docker start mysql-course: the data is kept in the volume.
Port already in use
If another MySQL server is already running on your computer, Docker fails with port is already allocated or address already in use. Map the container to a different host port, for example -p 3307:3306, and connect to port 3307. A simple password like secret is fine only on a training machine.
Option 2. Install MySQL on Your Computer
| OS | Installation | Starting and connecting |
|---|---|---|
| Windows | Download the MySQL Community Server 8.4 MSI package from dev.mysql.com and install it. Right after installation, run MySQL Configurator: it sets up the server and asks you to choose a root password | Configurator registers the server as a Windows service that starts automatically. Connect with mysql -uroot -p; for the command to be found, add C:\Program Files\MySQL\MySQL Server 8.4\bin to PATH |
| macOS | brew install [email protected]. The formula is keg-only: the client is not added to PATH automatically, so add it withecho 'export PATH="$(brew --prefix [email protected])/bin:$PATH"' >> ~/.zshrc and open a new terminal | brew services start [email protected]. The root password is empty after installation: connect with mysql -uroot and set a password with mysql_secure_installation |
| Linux (Ubuntu, Debian) | sudo apt updatesudo apt install mysql-server | sudo systemctl status mysql checks the service. Connect with sudo mysql (by default root logs in through the socket, without a password) |
The version you get from a package manager depends on the system: on Ubuntu 26.04 apt installs MySQL 8.4, older releases may give you the end-of-life 8.0, and brew install mysql without a version installs the latest Innovation release 26.x. Any of them works for the practice queries in this module. After installation, check that the client is found and the server responds:
mysql --version
mysql -uroot -p The first command prints the client version, for example mysql Ver 8.4.8 for Linux on x86_64 (MySQL Community Server - GPL); the second asks for the password and opens the mysql> prompt. If you get command not found or 'mysql' is not recognized as an internal or external command, the MySQL bin folder is not in PATH.
Graphical Clients
You can type queries in the console, but tables are easier to work with in a graphical client. Every client needs the same connection settings: host 127.0.0.1 (or localhost), port 3306 (or the port you mapped), user root and its password. With the console mysql client on Linux and macOS, prefer -h 127.0.0.1 when the server runs in Docker - see the FAQ below.
| Client | Highlights |
|---|---|
| MySQL Workbench | The official free MySQL client (a separate download from dev.mysql.com): query editor, table browser, schema diagrams |
| DBeaver Community | Free, works with MySQL, PostgreSQL, SQLite and many other databases |
| Database tools in IntelliJ IDEA Ultimate | Built into the IDE: convenient if you already write Java code in IntelliJ IDEA (not available without the Ultimate subscription) |
The lightweight HeidiSQL client and the rest of the course software are listed on the Java Developer Tools checklist.
Your First SQL Query in MySQL
Your first query takes five steps: create a database, select it, create a table, insert rows and read them back. Connect with the mysql client (see above) and run the commands in order; each one ends with a semicolon.
Create the forum database and make it the current one:
CREATE DATABASE forum;
USE forum; Create the users table and check that it exists:
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
SHOW TABLES; +-----------------+
| Tables_in_forum |
+-----------------+
| users |
+-----------------+ Insert two rows and read the whole table:
INSERT INTO users (username, email) VALUES
('Alice', '[email protected]'),
('Bob', '[email protected]');
SELECT * FROM users; +----+----------+-------------------+
| id | username | email |
+----+----------+-------------------+
| 1 | Alice | [email protected] |
| 2 | Bob | [email protected] |
+----+----------+-------------------+ You did not fill in the id column - MySQL numbered the rows itself thanks to AUTO_INCREMENT. This column is the table’s primary key; keys are explained in a separate lesson of this module. What will the next query print?
SELECT username, email FROM users WHERE id = 2; +----------+-----------------+
| username | email |
+----------+-----------------+
| Bob | [email protected] |
+----------+-----------------+ The syntax of CREATE, INSERT and SELECT and the column data types (INT, VARCHAR) are covered in detail in the next lessons of this module. Later, the same queries are sent from Java code through JDBC.
What can go wrong
ERROR 1046 (3D000): No database selected means you skipped USE forum;. ERROR 1007 (HY000): Can't create database 'forum'; database exists means the database has already been created: skip the first command or write CREATE DATABASE IF NOT EXISTS forum;.
Frequently Asked Questions
Are MySQL and SQL the same thing?
No. SQL is a query language, and MySQL is one of the database management systems that understand it. You would write nearly the same queries for PostgreSQL or Oracle, with small differences in dialect. The terms are compared in the table above.
Which database should a beginner Java developer learn first?
Start with MySQL or PostgreSQL: both are free, widely used in Java projects and supported by JDBC and Hibernate. For learning SQL there is almost no difference between them; this course uses MySQL.
How is a NoSQL or network database different from a relational one?
A relational database keeps data in tables with predefined columns and links them with queries. Network, document and graph databases store data in other structures (records with pointers, JSON documents, nodes and edges) and have no rigid table. Relational databases remain the standard for strictly structured data such as orders and payments.
Which MySQL version should I install: 8.4, 9.7 or 26.x?
For learning and for real projects, pick an LTS line: 8.4 or 9.7 receive fixes for several years. The 26.x Innovation releases come out every quarter and quickly replace each other - they are for trying out new features. Versions 5.7 and 8.0 are no longer supported and are not used in new projects.
Why can’t mysql -uroot -p on my computer connect to MySQL in Docker?
On Linux and macOS, the mysql client treats the host localhost as a Unix socket, not a network address, so it cannot see the server inside the container and fails with ERROR 2002 (HY000): Can't connect to local MySQL server through socket. Specify the address explicitly: mysql -h 127.0.0.1 -P 3306 -uroot -p. Graphical clients connect over the network and do not have this problem.
Comments