Databases

SQL

SQL (Structured Query Language) — декларативный язык запросов к реляционным базам данных: вы описываете нужный результат, а СУБД сама решает, как его получить.

Что такое SQL

SQL (Structured Query Language, язык структурированных запросов) — язык, на котором обращаются к реляционным базам данных. Его ключевая черта — декларативность: вы описываете, какой результат нужен, а не как его получить. Как именно читать таблицы, в каком порядке их соединять и какой индекс использовать, решает планировщик СУБД.

SELECT city, COUNT(*) AS users
FROM users
WHERE created_at >= '2026-01-01'
GROUP BY city
HAVING COUNT(*) > 10
ORDER BY users DESC
LIMIT 5;

Здесь нет ни одного цикла и ни одного обращения к файлу — только описание выборки. Произносят название и как «эс-кю-эль», и как «сиквел».

Группы команд

Группа Расшифровка Команды
DML Data Manipulation Language SELECT, INSERT, UPDATE, DELETE
DDL Data Definition Language CREATE, ALTER, DROP, TRUNCATE
DCL Data Control Language GRANT, REVOKE
TCL Transaction Control Language BEGIN, COMMIT, ROLLBACK

Порядок выполнения запроса

Пишется запрос не в том порядке, в котором исполняется. Это объясняет самую частую ошибку новичка — попытку отфильтровать агрегат через WHERE:

FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

WHERE отрабатывает до группировки и про COUNT(*) ещё ничего не знает — фильтровать агрегаты нужно в HAVING. По той же причине псевдоним из SELECT доступен в ORDER BY, но не в WHERE.

COUNT в SQL

COUNT() — агрегатная функция, возвращающая число строк. Три её формы ведут себя по-разному, и разница регулярно превращается в баг:

SELECT COUNT(*)         FROM orders;  -- все строки таблицы
SELECT COUNT(phone)     FROM orders;  -- строки, где phone IS NOT NULL
SELECT COUNT(DISTINCT user_id) FROM orders;  -- уникальные значения

COUNT(*) считает строки, COUNT(column) пропускает NULL. На больших таблицах точный подсчёт всегда стоит полного прохода по данным: в PostgreSQL SELECT COUNT(*) на десятках миллионов строк — это секунды, поэтому для пагинации точное число обычно заменяют оценкой или keyset-подходом.

JOIN — соединение таблиц

SELECT u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id      -- только совпадения
LEFT JOIN refunds r ON r.order_id = o.id;  -- все заказы, возвраты если есть

Соединение работает через ключи: внешний ключ orders.user_id ссылается на первичный users.id. INNER JOIN оставляет только парные строки, LEFT JOIN сохраняет все строки левой таблицы и подставляет NULL там, где пары нет.

Что такое индекс в SQL

Индекс — отдельная структура (обычно B-дерево), которая позволяет найти строки по значению колонки, не читая таблицу целиком. Без него WHERE email = ... вынуждает СУБД просмотреть все строки.

CREATE INDEX idx_orders_user_created ON orders (user_id, created_at);

EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 42;
-- Seq Scan   → индекс не используется, читается вся таблица
-- Index Scan → индекс работает

Индексы ускоряют чтение и замедляют запись: каждый INSERT обновляет ещё и все индексы таблицы. Детали — в статье про индексы в БД.

SQL-сервер — это что

Термином «SQL-сервер» называют две разные вещи, и их постоянно путают:

  • Сервер БД вообще — машина или процесс, обслуживающий запросы: PostgreSQL, MySQL, любая другая СУБД.
  • MS SQL Server — конкретный продукт Microsoft с диалектом T-SQL.

Диалекты

Стандарт ANSI SQL реализован везде частично, поэтому переносимость запросов ограничена:

Задача PostgreSQL MySQL MS SQL Server
Ограничить выборку LIMIT 10 LIMIT 10 TOP 10
Автоинкремент GENERATED AS IDENTITY AUTO_INCREMENT IDENTITY(1,1)
Текущее время NOW() NOW() GETDATE()
Приведение типа x::int CAST(x AS SIGNED) CAST(x AS INT)

Базовый SELECT ... WHERE ... JOIN переносится почти без правок, а функции дат, типы и оконные конструкции — уже нет.

Связанные термины

Готовы запустить GPU-задачу?

Запустить GPU-сервер