Казалось бы, старая 50-летняя технология в эпоху нейросетей утратила актуальность, но не SQL. Её востребованность только растёт, на что указывает упоминание в 16 000 вакансий на hh.ru, ведь большая доля информации вся информация, за исключением мультимедиа, хранится в базах данных. Для обращения к ним используют SQL-запросы – команды, которые позволяют считывать, добавлять, удалять, редактировать, фильтровать и сортировать информацию. В статье рассмотрим основные типы SQL-запросов, их особенности и примеры применения, она станет своего рода шпаргалкой для новичков и тех, кто забыл. А попрактиковаться в написании запросов можно при помощи интерактивных тренажёров SQL.

Типы запросов в зависимости от функционального назначения
Общепринятая классификация, в которой легко ориентируются даже новички.
Data Definition Language (DDL) – определение данных
Тип включает команды создания и изменения структуры базы данных: таблиц, индексов и иных объектов.
Создаёт новые объекты: базы данных, таблицы, индексы, определяет их структуру и свойства.
—Простая таблица
CREATE TABLE users (
id INT PRIMARY KEY, — Идентификатор
name VARCHAR(50), — Имя пользователя (до 50 символов)
created_at DATE — Дата добавления записи
);
—Таблица с ограничениями: правила целостности для корректности данных.
CREATE TABLE products (
product_id INT PRIMARY KEY, — ID товара
name VARCHAR(100) NOT NULL, — Название (обязательное поле)
price DECIMAL(10,2) CHECK (price > 0), — Цена, должна быть > 0
category VARCHAR(50) DEFAULT ‘General’, — Категория, стандартная – General
category_id INT, — ID категории для связи
UNIQUE (name, category), — Уникальность сочетания имя + категория
FOREIGN KEY (category_id) REFERENCES categories(id) — Связь с таблицей категорий
);
—Обычный индекс: ускоряет поиск по полю.
CREATE INDEX idx_employee_email ON employees(email);
—Составной индекс: оптимизирует запросы с условиями ( фамилия клиента и дата).
CREATE INDEX idx_order_customer_date ON orders (customer_id, order_date);
Меняет структуру таблицы: добавление, удаление, изменение элементов без пересоздания.
— Вводит новый столбец (номер телефона клиентов)
ALTER TABLE customers ADD COLUMN mobile_phone VARCHAR(20);
— Устанавливает ограничение CHECK (гарантирует, что цена будет положительной)
ALTER TABLE products ADD CONSTRAINT price_positive CHECK (price > 0);
— Добавляет индекс (ускорит поиск клиентов по почте)
ALTER TABLE users ADD INDEX idx_user_email (email);
— Изменяет тип данных столбца и расширит максимальную длину имени
ALTER TABLE employees MODIFY COLUMN name VARCHAR(100);
— Добавляет новый столбец (для хранения номера телефона длиной до 20 знаков)
ALTER TABLE employees
ADD COLUMN phone VARCHAR(20);

Безвозвратно стирает элементы базы данных с содержимым. Восстановить их после этого в большинстве случаев можно только с резервной копии.
— Таблицы
DROP TABLE temp_data;
— Индекса
DROP INDEX idx_employee_email;
— Представление (виртуальная таблица-запрос, которая хранится в оперативной памяти)
DROP VIEW employee_summary;
— Базу данных с настройками и содержимым
DROP DATABASE test_database;
Мгновенно удаляет содержимое таблицы с настройками, но её структуру оставляет. Работает быстрее DELETE в 10–100 раз, но не без поддержки фильтрации WHERE и отката действий.
TRUNCATE TABLE name; — нужно указать только название таблицы.
Добавляет поясняющий текст.
— Описание к таблице
COMMENT ON TABLE users IS ‘Зарегистрированные пользователи’;
email для входа’;
Запросы из групп
— Комментарий к столбцу
COMMENT ON COLUMN users.email IS ’email для входа’;
Запросы из группы DDL концентрируются на содержимом базы данных, её таблицах. Откатить сделанные с их помощью изменения без резервной копии можно не всегда.
Data Manipulation Language (DML) – манипуляции с данными
Запросы для обработки содержимого таблиц. Они делают выборку, добавляют, изменяют записи. Результаты их отправки можно откатить с помощью транзакций.
Извлекает содержимое таблиц с сортировкой, фильтрацией, группировкой, агрегированием информации. Применяется только для чтения данных.
— Выборка всех колонок из таблицы
SELECT * FROM users;
— Сортировка результатов по убыванию стоимости
SELECT * FROM products ORDER BY price DESC;
— Конкретных колонок (имя, почта) с условием – совершеннолетние
SELECT name, email FROM users WHERE age >= 18;

Пример таблицы
Исходные данные для демонстрации работы запроса
Вывод

Как работает SQL-запрос типа DML
Отобразит только совершеннолетних пользователей: имя и возраст
Вставляет новые строки в таблицу, содержимое которых соответствует типам столбцов.
— Добавление одной строки
INSERT INTO employees (first_name, last_name, email, hire_date, salary, id)
VALUES (Петр, ‘Иванов’, petr.ivanov@company.com’, ‘2025-12-12’, 65000, 1);
— Добавление трёх записей
INSERT INTO products (name, price, category) VALUES
(‘Laptop’, 1999.99, ‘Electronics’),
(‘Mouse’, 26, ‘Electronics’),
(‘Keyboard’, 45.50, ‘Electronics’);

Как добавить запись в базу данных
Информация вставляется под последней строчкой.
Изменяет существующие данные в таблице. Для указания строк используйте WHERE, иначе затронете всю таблицу.
— Обновление записи
UPDATE employees
SET salary = 7000, department_id = 2
WHERE employee_id = 1;
— Нескольких записей по условию: категория «Электроника» и «Количество товаров»
UPDATE products
SET price = price * 0.9
WHERE category = ‘Electronics’ AND stock_quantity > 100;
Стирает строки с содержимым.
— Убирает указанные записи
DELETE FROM orders WHERE order_date < ‘2025-12-11’ AND status = ‘cancelled’;
— Опасный запрос (построчно очистит таблицу)
DELETE FROM temp_logs;
Проверяет, существует ли запись, и обновляет её либо создаёт новую. Применяют для синхронизации данных.
| id | name | |
|---|---|---|
| C0001 | test@mail.ru | Олег |
| C0002 | user@gmail.com | Марина |
| C0003 | blabla@mail.ru | Пётр |
— Пример: синхронизация данных пользователей
— Если клиент с почтой blabla@mail.ru’ есть, изменит его имя
— Если нет, создаст новую строку
MERGE INTO customers AS target
USING (VALUES (blabla@mail.ru’, ‘Иван’)) AS source(email, name)
ON target.email = source.email — Сравниваем по email
WHEN MATCHED THEN — Вдруг есть совпадение
UPDATE SET name = source.name — Обновляем имя
WHEN NOT MATCHED THEN — Не нашли
INSERT (email, name) VALUES (source.email, source.name); — Создаём нового
| id | name | |
|---|---|---|
| C0001 | test@mail.ru | Олег |
| C0002 | user@gmail.com | Марина |
| C0003 | blabla@mail.ru | Иван |
Команды DML работают с содержимым баз данных
Data Control Language (DCL) – запросы управления доступом.
Команды для обеспечения безопасности или управления правами пользователей. Позволяют указывать, может читать, изменять или администрировать данные. Применяются администраторами баз данных, тестировщиками, специалистами по безопасности.
Выдаёт привилегии для работы с таблицами, представлениями, процедурами, определяет круг привилегий для каждого пользователя.
— Только чтение табличных данных
GRANT SELECT ON employees TO user_analyst;
— Все привилегии на работу с БД company_db
GRANT ALL PRIVILEGES ON company_db.* TO admin_user;
Забирает ранее выданные права.
— Отзывает возможность обновлять таблицу employees у пользователя junior
REVOKE UPDATE ON employees FROM junior;
— Отзывает все права на таблицу sensitive у temp_user
REVOKE ALL PRIVILEGES ON sensitive FROM temp_user;
— Частичный отзыв (редактору оставляем право чтения)
REVOKE INSERT, UPDATE ON articles FROM editor;
Добавляет юзеров и позволяет управлять ими.
— Создание аккунта с именем ‘new_employee’ и паролем ‘secure_pass’
— ‘@localhost’ означает доступ только с локального сервера
CREATE USER ‘new_employee’@’localhost’ IDENTIFIED BY ‘secure_pass’;
— Изменение пароля на ‘new_pass’ для user1
ALTER USER ‘user1’@’localhost’ IDENTIFIED BY ‘new_pass’;
Явно запрещает действия, даже если пользователь имеет другие разрешения или права через роли. Работает поверх других привилегий.
— Запрещает удаление данных из таблицы
DENY DELETE ON sensitive_data TO PUBLIC;
— Нельзя менять структуру таблицы (даже администраторам)
DENY ALTER ON critical_tables TO ALL USERS;
Запросы DCL позволяют управлять правами пользователей, чем минимизируют риски несанкционированного доступа, изменения структуры и содержимого хранилища.
Transaction Control Language (TCL) – запросы управления транзакциями
TCL предлагает команды для управления транзакциями – логическими единицами работы с базой данных. Их задача — контроль целостности информации. Используются администраторами БД, системными архитекторами, DevOps-специалистами.
Указывает на начало блока операций, которые будут выполнены как единое целое. Привнесённые изменений будут невидимы пользователям (осуществляются в оперативной памяти) до подтверждения.
— Явное начало транзакции (работают одинаково)
BEGIN TRANSACTION; или START TRANSACTION;
Фиксирует все изменения, сделанные в текущей транзакции, делая их постоянными и видимыми для других пользователей. После COMMIT откат становится невозможен.
— Начало
BEGIN TRANSACTION;
— Добавление счётчика с начальным балансом
INSERT INTO accounts (account_id, balance) VALUES (1001, 1000.00);
— Подтверждение информации
COMMIT;
— Новый счёт 1001 виден всем, коррективы сохранены
Отменяет сделанные в текущей транзакции изменения, возвращая базу данных к состоянию до её начала.
— Запуск
BEGIN TRANSACTION;
— Опасно: удваиваем цены в каталоге
UPDATE products SET price = price * 2;
— Стоимость временно увеличена, здесь мы понимаем, что нужно не в 2, а в 0,02 раза (на 2%), откатываемся
ROLLBACK;
— Возвращаем исходные цены
Создаёт точку в транзакции, к которой можно вернуться в случае частичного отката.
— Начинаем
BEGIN TRANSACTION;
— Шаг 1: создание нового клиента
INSERT INTO customers (name, email) VALUES (‘Test User’, ‘test@example.com’);
— Пользователь на время добавлен
— Добавление точки отката
SAVEPOINT customer_created;
— Шаг 2: создание для него заказа
INSERT INTO orders (customer_id, amount) VALUES (LAST_INSERT_ID(), 5000);
— Заказ не прошёл — возврат до момента, когда только добавили клиента
— ROLLBACK TO customer_created;
— Пользователь останется, заказ исчезнет
— В случае успеха подтверждаем транзакцию
COMMIT;
— Сохраняем заказ и клиента
TCL-запросы управляют транзакциями: запускают, отказывают, фиксируют и подтверждают их.
Data Query Language (DQL)
Категория содержит единственную команду – SELECT. Её выделяют отдельно из-за гибкости, и востребованности – на неё приходится свыше 80% всех запросов.

Таблица сотрудников
Пример того, как работают TCL-запросы
—Отобразит всю таблицу целиком
SELECT * FROM employees;
—Только фамилию, имя и почту
SELECT first_name, last_name, email FROM employees;

Исходные данные
Таблица с клиентами для демонстрации работы запросов типа DQL
—Сотрудники с доходом свыше 50 000 с отдела IT
SELECT * FROM employees WHERE department = ‘IT’ AND salary > 50000;

Результат выполнения запросы SELECT
Команда подтянула информацию с другой таблички без их изменения
Технически DQL относят к DML, но часто её выделяют в отдельную категорию.
Классификация запросов по числу таблиц
Запросы делят по количеству задействованных таблиц.
Однотабличные — это запросы, работающие с одной таблицей. Это выборка, фильтрация, обновление, удаление, информации, математические операции.
—Подсчёт покупателей, вернувших товар в этом месяце
SELECT COUNT(DISTINCT customer_id) AS unique_customers
FROM orders
WHERE order_date >= DATE_TRUNC(‘month’, CURRENT_DATE);
Это SQL-операции, которые затрагивают содержимое двух и более таблиц с помощью операторов JOIN. Они позволяют извлекать связанные данные, распределённые по разным объектам хранилища.
Основные типы:
- INNER JOIN – отобразит строки, у которых будут совпадение в двух таблицах.
- LEFT JOIN – берёт все строки из первой таблицы и соответствующие строки из второй таблички; если совпадений нет — подставляет NULL.
- RIGHT JOIN – аналог LEFT, только возвращает все строки второй таблицы.
- FULL JOIN – отображает строки, где есть совпадение хотя бы в одной из таблиц.
Рассмотрим на примере.
Таблица employees.
| employee_id | employee_name | dep_id | salary |
|---|---|---|---|
| 1 | Сергей Пахно | 1 | 60000 |
| 2 | Анна Горбенко | 2 | 75000 |
| 3 | Олег Коваленко | 3 | 52000 |
| 4 | Марина Лебедева | NULL | 48000 |
| 5 | Дмитрий Орлов | 2 | 82000 |
Таблица departments.
| dep_id | department_name |
|---|---|
| 1 | Маркетинг |
| 2 | Продажи |
| 3 | Разработка |
Покажет работников и их отделы, включая тех, у кого отсутствует идентификатор отдела dep_id — будет NULL.
SELECT e.employee_name, d.department_name FROM employees e LEFT JOIN departments d ON e.dep_id = d.dep_id;
Результат выполнения.
| employee_name | department_name |
|---|---|
| Сергей Пахно | Маркетинг |
| Анна Горбенко | Продажи |
| Олег Коваленко | Разработка |
| Марина Лебедева | NULL |
| Дмитрий Орлов | Продажи |
Для всех сотрудников кроме Лебедевой подтянулись названия отделов, где они работают.
Типы подзапросов
Помимо запросов в SQL существуют подзапросы— это вложенные SELECT-операции, которые используются внутри других SQL-запросов для вычисления промежуточных значений, фильтрации данных или выполнения сложных аналитических задач. Они позволяют решать то, что невозможно или неудобно реализовать обычным JOIN, при этом делают запросы более гибкими.
Подзапросы или вложенные SELECT-запросы. Бывают двух типов.
Ссылаются на колонки из внешнего запроса и выполняются для его строк, поэтому работают медленно. Они не самые эффективные, зато незаменимые при решении сложных задач, например, когда нужно вычислять значение индивидуально для каждой строки. Как пример, искать записи, превышающие средний показатель внутри категории.
— Вывод последнего заказа клиентов
SELECT
customer_id, — ID клиента
order_id, — Идентификатор заказа
order_date, — Дата создания
total_amount — Стоимость
FROM orders o1 — Внешний запрос (o1) перебирает все заказы.
WHERE order_date = (
SELECT MAX(order_date) — Ищем максимальную дату заказа конкретного клиента.
FROM orders o2 — Вложенный подзапрос (o2) работает для каждого клиента отдельно.
WHERE o2.customer_id = o1.customer_id — Ссылка на внешний запрос, подзапрос выполняется построчно.
); — Строчки, где order_date = MAX(order_date), и есть последние заказы клиентов.
Используют в условиях WHERE или HAVING с предикатами IN, ANY, ALL, EXISTS. Они выполняются один раз и помогают решать сложные аналитические задачи.
— Поиск продуктов, которые хотя бы раз заказали от 10 штук
SELECT
product_id, — Идентификатор продукта
product_name, — Название
price — Стоимость
FROM products
WHERE product_id IN (
SELECT product_id — Находим ID продуктов с 10+ заказами
FROM order_items
WHERE quantity > 10
);
Подзапросы в SQL позволяют решать сложные задачи выборки и фильтрации данных, делая запросы гибкими и наглядными
Классификация запросов в зависимости от типа операций
Существует формальная классификация, которая помогает новичкам ориентироваться в разнообразии команд SQL, но часть функций в ней пересекается — могут относиться к двум категориям.
| Категория | Тип запроса / функции | Примеры | Описание |
|---|---|---|---|
| Основные | SELECT | SELECT name, age FROM users | Выбор данных из таблицы |
| INSERT | INSERT INTO users (name, age) VALUES (‘Иван’, 30) | Добавление новых записей | |
| UPDATE | UPDATE users SET age=31 WHERE name=’Иван’ | Обновление записей | |
| DELETE | DELETE FROM users WHERE age > 100 | Удаление записей | |
| Строковые | UPPER() | SELECT UPPER(name) FROM users | Преобразование в верхний регистр |
| LOWER() | SELECT LOWER(email) FROM contacts | Преобразование в нижний регистр | |
| CONCAT() | SELECT CONCAT(first_name, ‘ ‘, last_name) FROM employees | Объединение строк | |
| SUBSTRING() | SELECT SUBSTRING(phone, 1, 3) FROM clients | Извлечение части строки | |
| TRIM() | SELECT TRIM(address) FROM locations | Удаление пробелов с обеих сторон | |
| Дата/время | NOW() | SELECT NOW() AS current_datetime | Текущая дата и время |
| CURDATE() | SELECT CURDATE() AS today | Текущая дата | |
| CURTIME() | SELECT CURTIME() AS current_time | Текущее время | |
| YEAR() | SELECT YEAR(birth_date) FROM persons | Извлечение года из даты | |
| MONTH() | SELECT MONTH(created_at) FROM orders | Извлечение месяца (1-12) | |
| DAY() | SELECT DAY(delivery_date) FROM shipments | Извлечение дня месяца | |
| DATE_FORMAT() | SELECT DATE_FORMAT(date, ‘%d.%m.%Y’) FROM events | Форматирование даты | |
| DATEDIFF() | SELECT DATEDIFF(end_date, start_date) FROM projects | Разница между датами в днях | |
| Агрегатные функции | COUNT() | SELECT COUNT(*) FROM users | Подсчёт количества строк |
| SUM() | SELECT SUM(salary) FROM employees | Сумма значений | |
| AVG() | SELECT AVG(price) FROM products | Среднее значение | |
| Соединения | JOIN | SELECT u.name, o.date FROM users u JOIN orders o ON u.id=o.user_id | Объединение таблиц |
| Логические | BOOLEAN (BOOL, BIT) | CREATE TABLE users (is_active BOOLEAN); | Хранения статуса, состояния: TRUE или лжи FALSE) |
| Бинарные | BLOB, BINARY, VARBINARY | CREATE TABLE docs (file_content BLOB); | Хранение «сырых» двоичных данных: изображений, файлов, паролей |
Для облегчения ориентации SQL-запросах их делят в соответствие с совершаемыми типами операций.
FAQ (Часто задаваемые вопросы)
Запросом называют инструкцию СУБД, где описан, что нужно сделать. Она состоит из одной строчки, хотя сложные длинные команды могут записывать в несколько строк для удобства чтения кода.
Команду на отображение имён пользователей с таблицы users, которым 30+ лет с сортировкой по имени в алфавитном порядке, можно записать двумя способами:
SELECT name, age FROM users WHERE age > 30 ORDER BY name;
или
SELECT name, age
FROM users
WHERE age > 30
ORDER BY name;
А теперь представьте более сложную инструкцию, записанную в одну строчку.
SELECT u.name, COUNT(o.id) AS orders
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.status = ‘completed’
GROUP BY u.name
HAVING COUNT(o.id) > 5
ORDER BY orders DESC;
Из чего состоят SQL-запросы:
- Ключевые слова — зарезервированные команды SQL (SELECT, FROM, WHERE и т.д.)
- Идентификаторы — имена таблиц, колонок, схем.
- Литералы — конкретные значения (строки, числа, даты).
- Операторы — символы для сравнения, арифметические и логические действия.
- Разделители — запятые, скобки, точки с запятой.
Базовый SQL-запрос может включать до 7 клауз или предложений – ключевых структур запроса:
- SELECT [модификаторы] список_колонок – ключевое слово для выбора столбцов.
- FROM источник_данных – указывает, с какой таблицей или источником данных работать.
- [WHERE условия_фильтрации] – фильтрует строки по указанным условиям.
- [GROUP BY колонки_группировки] – группирует данные по указанным столбцам.
- [HAVING условия_для_групп] – применяет условия к уже сгруппированным данным.
- [ORDER BY колонки_сортировки] – сортирует результат по возрастанию или убыванию.
- [LIMIT число_записей] – ограничивает количество выводимых строк.
Важно: первые две команды — SELECT и FROM — обязательны. Остальные используются при необходимости.
Пример: вывод имён 5 пользователей с наибольшим числом завершённых заказов, у которых заказов больше двух.
| SELECT name, COUNT(o.id) AS orders | выбор столбцов и подсчет заказов |
| FROM users u | таблица пользователей |
| JOIN orders o ON u.id = o.user_id | соединение с заказами |
| WHERE o.status = ‘completed’ | фильтрация по статусу |
| GROUP BY name | группировка по имени |
| HAVING COUNT(o.id) > 2 | только пользователи с >2 заказами |
| ORDER BY orders DESC | сортировка по количеству заказов |
| LIMIT 5; | вывести первые 5 записей |
Все поддерживаемые типы мы вынесли в компактную табличку с примерами.
| Категория | Тип данных | Описание | Пример | Пример значения |
|---|---|---|---|---|
| Числовые | INT | Целое число | age INT | 30 |
| BIGINT | Большое целое число | population BIGINT | 150000 | |
| DECIMAL(10,2) | Точное число с дробной частью | price DECIMAL(10,2) | 1999.99 | |
| FLOAT | Приближённое число | rating FLOAT | 4.7 | |
| Строковые | CHAR(2) | Фиксированная длина | country_code CHAR(2) | ‘DataBase’ |
| VARCHAR(255) | Переменная длина | email VARCHAR(255) | ‘user@mail.com’ | |
| TEXT | Длинный текст | description TEXT | ‘Отличный товар’ | |
| Дата/время | DATE | Только дата | birth_date DATE | 2000-04-12′ |
| TIME | Только время | start_time TIME | ’14:30:00′ | |
| TIMESTAMP | Дата и время | created_at TIMESTAMP | ‘2025-12-13 10:45:00’ | |
| Логические | BOOLEAN | Да / нет | is_active BOOLEAN | TRUE |
| Двоичные | BLOB | Файлы, изображения | photo BLOB | — |
| Прочие | ENUM | Значение из списка | status ENUM(‘new’,’done’) | ‘new’ |
| UUID | Идентификатор | id UUID | ‘550e8400-40000’ |
информация о всех столбцах таблиц.
SELECT Column_Name, DATA_TYPE, Char_Max_Lenght
FROM DataBaseName.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ‘Название_таблицы’
AND COLUMN_NAME = ‘Название_поля’;
Здесь:
DATA_TYPE — тип данных поля (INT, VARCHAR, DATE и т.д.)
Char_Max_Lenght — максимальная длина (актуально для строк)
Запрос покажет тип и параметры выбранного столбца.
SQL позволяет работать с информацией в базах данных: читать, добавлять, изменять, удалять, группировать, фильтровать и управлять правами доступа. Все запросы делятся на четыре группы: DDL отвечает за создание и изменение структуры базы, DML — за работу с содержимым таблиц, DCL управляет правами пользователей, а TCL обеспечивает контроль транзакций. Их изучение эффективно только через практику, для чего созданы интерактивные SQL-тренажеры. Освоив базовые команды и принципы работы, вы сможете податься в десятки профессий или повысите свою ценность на рынке труда.