SQL это язык запросов: что он делает
SQL расшифровывается как Structured Query Language, то есть «язык структурированных запросов». Вы описываете результат, например покупателей с покупками дороже заданной суммы. Система управления базами данных, сокращённо СУБД, выполняет запрос.
Строка таблицы представляет отдельную запись, например заказ. Столбец хранит свойство: номер, дату или сумму. Связи позволяют собрать информацию из нескольких таблиц.
SQL относится к декларативным языкам: вы задаёте, что получить, а способ выполнения выбирает СУБД. Это специализированный язык программирования; интерфейс сайта создают другими средствами.
Для чего нужен SQL и кто его использует
Язык SQL помогает найти неоплаченные покупки, посчитать выручку по покупателям или сверить остатки. Одна база может обслуживать сайт, внутреннюю программу и отчётность. Для анализа обычно достаточно прав на чтение.
- Аналитик использует SQL для выборки, проверки показателей и подготовки отчётов.
- Разработчик связывает базу с приложением, сохраняет заявки и обновляет статусы.
- Тестировщик проверяет, какие записи появились после действия пользователя.
- Администратор базы управляет доступом, следит за выполнением запросов и восстановлением информации.
СУБД и диалекты SQL: в чём разница
База данных хранит информацию, СУБД управляет её хранением, SQL служит языком обращения к системе. SQL Server, например, является СУБД.
Диалекты SQL различаются функциями, типами данных и синтаксисом. Все примеры статьи написаны для PostgreSQL. При переносе проверяйте документацию другой системы.
| Система | Что нужно знать начинающему |
|---|---|
| PostgreSQL | СУБД с поддержкой SQL; используется во всех примерах ниже. |
| MySQL | Реляционная СУБД со своим набором расширений языка. |
| SQLite | Встраиваемая SQL-база, которой не нужен отдельный серверный процесс. |
| Microsoft SQL Server | Реляционная СУБД; для запросов и программирования используется T-SQL. |
SQL и NoSQL: как выбрать модель данных
SQL обозначает язык, NoSQL объединяет системы с другими моделями данных, например документной. Для заказов со связями и ограничениями удобна реляционная модель. В документной MongoDB связанные сведения можно вложить в один документ; поля документов могут различаться.
Гибкая схема не отменяет проектирование: в MongoDB можно задавать правила проверки полей. Выбирайте модель по запросам и связям, а не по обещанию большей скорости. Само название SQL или NoSQL не определяет производительность.
Шпаргалка по SQL: основные команды и части запроса
Эта шпаргалка по SQL помогает выбрать конструкцию под задачу. SELECT, INSERT, UPDATE и DELETE являются самостоятельными операторами. WHERE, GROUP BY и ORDER BY задают условия внутри запроса.
DDL управляет структурой таблиц, DML работает с записями. Чтение через SELECT иногда выделяют в DQL. DCL управляет доступом: GRANT выдаёт права, REVOKE отзывает их. TCL управляет транзакциями через BEGIN, COMMIT и ROLLBACK.
| Конструкция SQL | Назначение | Пример задачи |
|---|---|---|
| SELECT / FROM | Выбор столбцов и источника | Показать номера и суммы покупок |
| WHERE | Фильтрация строк | Оставить только оплаченные покупки |
| ORDER BY | Сортировка результата | Показать дорогие покупки первыми |
| GROUP BY / HAVING | Группировка и отбор групп | Найти покупателей с большой суммой покупок |
| JOIN / ON | Соединение по условию | Добавить имя покупателя к заказу |
| INSERT INTO | Добавление записей | Сохранить новую покупку |
| UPDATE / SET | Обновление значений | Изменить сумму покупки |
| DELETE FROM | Удаление строк | Убрать учебную запись |
| CREATE TABLE / ALTER TABLE | Создание и изменение структуры | Создать таблицу или добавить столбец |
| DROP TABLE | Удаление таблицы целиком | Убрать ненужный учебный объект |
Таблицы, типы данных и ключи в SQL
Примеры относятся к вымышленному магазину: customers хранит покупателей, orders хранит покупки. Имена, номера и суммы придуманы для обучения. Используйте отдельную пустую базу.
PRIMARY KEY отличает запись от остальных: значения не повторяются и не могут быть NULL. REFERENCES задаёт внешний ключ. Вместе с NOT NULL он требует существующего покупателя для каждой покупки.
Имя хранится отдельно от заказов: при исправлении достаточно изменить запись покупателя. Такое разделение уменьшает повторение сведений и помогает избежать противоречий. Это практический смысл нормализации. Без ограничений PRIMARY KEY или UNIQUE таблица SQL может содержать одинаковые строки.
| Тип PostgreSQL | Что хранит | Где использовать |
|---|---|---|
| integer | Целые числа | Идентификатор id или количество |
| text | Текстовые строки | Имя name или описание |
| numeric | Числа с точной десятичной арифметикой | Стоимость покупки |
| date | Календарная дата | Дата покупки |
| boolean | Логическое значение | Признак выполнения условия |
CREATE TABLE customers (
id integer PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE orders (
id integer PRIMARY KEY,
customer_id integer NOT NULL REFERENCES customers(id),
total numeric NOT NULL CHECK (total >= 0)
);
INSERT: добавляем учебные записи
В INSERT значения следуют порядку перечисленных столбцов. Сначала добавляем покупателей, затем заказы. У Анны две покупки, у Бориса одна, у Веры ни одной.
Пропущенный столбец получает значение по умолчанию, а при его отсутствии NULL. Ограничения продолжают действовать: наш name нельзя пропустить без подходящего значения по умолчанию.
INSERT INTO customers (id, name) VALUES
(1, 'Анна'), (2, 'Борис'), (3, 'Вера');
INSERT INTO orders (id, customer_id, total) VALUES
(101, 1, 1200), (102, 1, 800), (103, 2, 1500);
SELECT и WHERE: выборка данных в SQL
SELECT задаёт столбцы результата, FROM указывает источник, WHERE отбирает строки. Запрос ниже покажет покупки, сумма которых больше 1000. Вы увидите номера 101 и 103; порядок здесь задан отдельно через ORDER BY.
AND и OR объединяют условия; скобки задают нужную логику. IN проверяет вхождение в список, BETWEEN включает обе границы диапазона. Условие name LIKE 'А%' найдёт имена, начинающиеся с «А»: знак % заменяет произвольную последовательность символов.
Звёздочка в SELECT означает все столбцы выбранного источника. Перечисляйте нужные поля явно: добавление столбца в таблицу тогда не изменит состав отчёта.
Ключевые слова SQL не зависят от регистра. Текстовые значения заключают в одинарные кавычки, точка с запятой завершает оператор.
SELECT id, total
FROM orders
WHERE total > 1000
ORDER BY id;
ORDER BY, DISTINCT и LIMIT: управляем результатом
ORDER BY сортирует строки: ASC по возрастанию, DESC по убыванию. Без него порядок не гарантирован. При одинаковых суммах сортировка по первичному ключу устраняет неоднозначность.
DISTINCT убирает повторы выбранных сочетаний значений. Например, SELECT DISTINCT customer_id FROM orders вернёт покупателей, у которых есть заказы. Сам DISTINCT не сортирует результат: для этого отдельно укажите ORDER BY.
LIMIT ограничивает число строк в PostgreSQL. Запрос ниже вернёт самую дорогую покупку: номер 103 с суммой 1500.
SELECT id, total
FROM orders
ORDER BY total DESC, id
LIMIT 1;
JOIN SQL: примеры соединения таблиц
JOIN в SQL соединяет строки по условию ON. Чтобы добавить имя к заказу, сопоставим customer_id с id покупателя. Обозначения c и o являются псевдонимами таблиц. Они сокращают запись и показывают, откуда взят столбец.
INNER JOIN вернёт только совпавшие пары: две строки Анны и одну Бориса. Веры в результате не будет. Несколько строк покупателя соответствуют его заказам.
| Вид JOIN | Какие строки сохраняет | Когда полезен |
|---|---|---|
| INNER JOIN | Только совпавшие по условию пары | Покупки с именами покупателей |
| LEFT JOIN | Все строки слева и совпадения справа | Покупатели, включая тех, кто ничего не заказал |
| RIGHT JOIN | Все строки справа и совпадения слева | Та же задача при обратном порядке таблиц |
| FULL JOIN | Совпадения и несовпавшие строки обеих сторон | Сверка независимых списков |
| CROSS JOIN | Все возможные пары строк | Получение сочетаний вариантов |
| SELF JOIN | Соединение таблицы с собой через разные псевдонимы | Сопоставление записей внутри одного справочника |
LEFT, RIGHT и FULL: внешние соединения
Внешние соединения SQL сохраняют строки без соответствия. На отсутствующей стороне результат содержит NULL. LEFT и RIGHT отличаются сохраняемой стороной, а FULL оставляет обе. Слово OUTER можно опустить: LEFT JOIN и LEFT OUTER JOIN равнозначны.
В нашей схеме NOT NULL и внешний ключ вместе запрещают заказ без существующего покупателя. Поэтому FULL JOIN даст те же строки, что LEFT JOIN, если слева customers, а справа orders.
Почему ON и WHERE дают разные результаты
При LEFT JOIN условие ON определяет, какие строки справа подходят для соединения. Условие WHERE отбирает уже полученный результат. Например, фильтр WHERE o.total > 1000 исключит покупателей без подходящих заказов.
Чтобы сохранить всех покупателей, добавьте ограничение суммы к условию ON. Тогда для человека без подходящей покупки останется строка с NULL. Такая разница часто объясняет пропавшие записи в отчёте.
SELECT c.name, o.id, o.total
FROM customers AS c
INNER JOIN orders AS o ON o.customer_id = c.id
ORDER BY o.id;
NULL и IS NULL: поиск отсутствующих значений
NULL в SQL обозначает отсутствие известного значения. Это не ноль и не пустая строка. Для проверки используйте IS NULL или IS NOT NULL. Обычное сравнение через знак равенства не подходит.
Следующий пример найдёт покупателей без заказов. LEFT JOIN сохранит всех покупателей, а WHERE оставит строки без совпавшего заказа. Проверяем o.id: первичный ключ заказа не бывает NULL в исходной таблице.
SQL-запрос вернёт Веру. По той же логике можно искать категории без товаров.
SELECT c.id, c.name
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
WHERE o.id IS NULL;
GROUP BY, HAVING и агрегатные функции SQL
GROUP BY собирает строки в группы с одинаковыми значениями указанных полей. Агрегатные функции считают итог по группе: SUM сумму, AVG среднее, MIN минимум, MAX максимум. COUNT помогает посчитать записи или заполненные значения.
COUNT(*) учитывает все строки результата. COUNT(o.id) считает только строки, где o.id не равен NULL. После LEFT JOIN это различие позволяет получить ноль покупок у Веры.
Результат: Анна с двумя покупками, Борис с одной, Вера без покупок. Группируем по id и имени, чтобы не смешать разных людей с одинаковыми именами.
WHERE фильтрует строки до группировки, HAVING отбирает группы по условию. Например, HAVING SUM(o.total) > 1800 оставит Анну. У неё общая сумма равна 2000. Фильтр WHERE o.total > 1800 решал бы другую задачу: поиск отдельных дорогих покупок.
SELECT c.id, c.name, COUNT(o.id) AS order_count
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY c.id;
Подзапросы, CTE и оконные функции SQL
Подзапрос позволяет использовать результат одной выборки внутри другой. Например, SELECT id FROM orders WHERE total > (SELECT AVG(total) FROM orders); найдёт покупки дороже среднего. На учебных записях это 101 и 103.
CTE, или общее табличное выражение, задаётся через WITH и даёт имя промежуточному результату в пределах запроса. Это помогает читать код, но само по себе не ускоряет вычисления.
Оконная функция считает показатель по связанным строкам, сохраняя отдельные записи. Ниже ROW_NUMBER нумерует покупки каждого человека по убыванию суммы. Внешний SELECT оставляет первую: Анне соответствует заказ 101, Борису 103. Сортировка по id разрешает равенство сумм.
CASE, текст и даты в аналитике
CASE WHEN total >= 1000 THEN 'крупный' ELSE 'обычный' END присваивает заказу категорию. Выражение можно поместить в SELECT рядом с его номером.
DATE хранит дату, TIMESTAMP хранит дату и время. Выражение EXTRACT(MONTH FROM DATE '2026-09-26') вернёт 9. Дата здесь учебная. Для помесячных отчётов понадобится дата покупки; в нашей таблице orders такого столбца пока нет.
WITH ranked AS (
SELECT id, customer_id, total,
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY total DESC, id
) AS rn
FROM orders
)
SELECT customer_id, id, total
FROM ranked
WHERE rn = 1
ORDER BY customer_id;
UPDATE, DELETE и транзакции SQL
UPDATE меняет значения через SET, DELETE удаляет строки. WHERE ограничивает область изменения. Без него команда затронет все доступные ей строки, если выполнится успешно.
В PostgreSQL транзакция объединяет действия в одно целое. BEGIN открывает её, COMMIT подтверждает изменения, ROLLBACK отменяет незавершённую транзакцию.
В примере после UPDATE сумма временно станет равной 1300. Затем DELETE удалит заказ, но ROLLBACK отменит оба действия. Итоговая запись останется с прежней суммой 1200. После COMMIT обычный ROLLBACK уже не вернёт зафиксированное изменение.
DELETE сохраняет структуру таблицы, DROP TABLE удаляет её вместе с содержимым. TRUNCATE очищает таблицу целиком, без WHERE. В PostgreSQL его можно откатить внутри незавершённой транзакции. Не запускайте примеры изменения на рабочей базе.
BEGIN;
SELECT id, total FROM orders WHERE id = 101;
UPDATE orders SET total = 1300 WHERE id = 101;
DELETE FROM orders WHERE id = 101;
ROLLBACK;
SELECT id, total FROM orders WHERE id = 101;
Частые ошибки при работе с SQL
Отсутствие ошибок синтаксиса ещё не означает правильный результат. Сначала запишите ожидаемый ответ на небольшом наборе, затем сравните с выборкой.
- Лишние строки после JOIN. Проверьте условие связи и число совпадений, прежде чем скрывать повторы через DISTINCT.
- Сумма выросла после соединения. Несколько связанных строк могли повторить одну покупку в результате.
- Пропали записи с NULL. Проверьте IS NULL и условия WHERE после внешнего соединения.
- Пользовательский ввод попал прямо в текст SQL. Передавайте значения отдельно через параметры библиотеки доступа к базе.
- Запрос работает медленно. EXPLAIN показывает план: чтение таблиц, соединения и оценки строк. EXPLAIN ANALYZE ещё и выполняет запрос. Наличие индекса не гарантирует его использование.
- Добавлены индексы на все поля. Каждый занимает место; вставки, удаления и изменения индексируемых значений добавляют работу по его обслуживанию.
Как начать изучение SQL на практике
Для примеров нужен работающий PostgreSQL и подключение к учебной базе. В терминале psql укажите параметры: psql -h localhost -U learner -d sql_training. learner и sql_training здесь условные имена существующей роли и базы. Замените их своими; команда сама базу не создаёт.
После подключения выполните SELECT 1; и проверьте, что получили 1. Затем запускайте блоки CREATE TABLE и INSERT по порядку. Руководство psql в источниках объясняет подключение и выполнение команд.
UNION объединяет результаты совместимого состава и убирает повторы; UNION ALL сохраняет их. В аналитике начинайте с вопроса и периода, проверяйте итог по исходным записям.
- Создайте таблицы и заполните их примерами из статьи.
- Напишите SELECT с фильтром и заранее определите ожидаемые строки.
- Сравните INNER JOIN и LEFT JOIN на покупателе без заказов.
- Посчитайте количество покупок и их сумму по каждому человеку.
- Измените запись внутри транзакции и проверьте результат после ROLLBACK.
- Добавьте покупателя с повторяющимся именем и проверьте правильность группировки.
Когда база данных нужна сайту или CRM
Если вы планируете сайт с заявками или учётом заказов, начните с описания информации. Какие записи нужно хранить, кто их меняет, какие отчёты нужны? Например, покупатель связан с заказами, а заказ с оплатой и доставкой.
Обсудить хранение заявок и заказов можно через разработку CRM-системы. Подготовьте список сущностей и рабочих сценариев. Знать SQL для постановки задачи необязательно. В seosite1 итоговую цену называем после брифа.
Источники
- PostgreSQL: язык SQL, типы, ограничения, изменение данных и запросы
- PostgreSQL: транзакции, COMMIT и ROLLBACK
- PostgreSQL: передача параметров при выполнении запросов
- MySQL: назначение СУБД и язык SQL
- SQLite: встраиваемая база без отдельного сервера
- Microsoft: SQL Server и Transact-SQL
- MongoDB: документная модель, гибкая схема и проверка данных
- PostgreSQL: подключение и выполнение запросов в psql