Изучите тему «Базы данных и SQL» с нуля
1Что такое реляционная база данных
Реляционная база данных хранит данные в таблицах. Таблица выглядит как электронная таблица: каждая строка — одна запись, каждый столбец — одно свойство.
В магазине может быть таблица customers со столбцами id, name и city и таблица orders со столбцами id, customer_id и total.
Первичный ключ — это столбец или набор столбцов, однозначно идентифицирующий каждую строку. Он никогда не повторяется и никогда не бывает пустым. Здесь это id каждой таблицы.
Внешний ключ — это столбец, ссылающийся на первичный ключ другой таблицы. В orders столбец customer_id показывает, какой клиент сделал заказ.
Так связываются таблицы: у одного клиента может быть много заказов, но каждый заказ принадлежит одному клиенту. Это связь «один ко многим».
SQL (Structured Query Language) — это язык, на котором создают таблицы, изменяют данные и задают вопросы о них.
Самопроверка Что такое первичный ключ?
- Индекс, ускоряющий поиск
- Первый столбец каждой таблицы
- Столбец или набор столбцов, однозначно идентифицирующий каждую строку
- Столбец, ссылающийся на строку в другой таблице
Ответ: Столбец или набор столбцов, однозначно идентифицирующий каждую строку. Первичный ключ уникален и никогда не равен NULL, поэтому он выбирает ровно одну строку. Столбец, ссылающийся на другую таблицу, — это внешний ключ.
2Чтение данных с помощью SELECT
Большинство вопросов касается оператора SELECT. Он состоит из предложений, которые всегда пишутся в таком порядке:
SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY …
- SELECT перечисляет нужные столбцы. DISTINCT удаляет повторяющиеся строки.
- FROM называет таблицу или объединённые таблицы.
- WHERE оставляет только строки, удовлетворяющие условию, например WHERE total > 20.
- GROUP BY помещает строки с одинаковым значением в одну группу, чтобы можно было считать или суммировать по группам.
- HAVING оставляет только группы, удовлетворяющие условию. В нём можно использовать агрегаты, а в WHERE нельзя.
- ORDER BY сортирует результат, по умолчанию по возрастанию; добавьте DESC, чтобы сначала шли наибольшие.
Агрегатные функции сводят много строк в одно значение: COUNT, SUM, AVG, MIN и MAX.
База данных выполняет предложения не в том порядке, в котором вы их пишете. Сначала выполняется FROM, затем WHERE, GROUP BY, HAVING, SELECT и в конце ORDER BY.
Другие операторы изменяют данные: INSERT добавляет строки, UPDATE изменяет строки, а DELETE удаляет строки. CREATE, ALTER и DROP изменяют сами таблицы.
Самопроверка Вам нужны только клиенты с более чем 5 заказами. Какое предложение фильтрует по COUNT(*) > 5?
- DISTINCT
- HAVING
- ORDER BY
- WHERE
Ответ: HAVING. Количество существует только после группировки строк, а HAVING фильтрует группы. WHERE выполняется до группировки, поэтому не может использовать агрегат вроде COUNT.
3Соединения, нормализация и транзакции
Соединение (join) объединяет строки двух таблиц по условию, обычно внешний ключ = первичный ключ:
FROM customers c JOIN orders o ON o.customer_id = c.id
- INNER JOIN (или JOIN) оставляет только строки, имеющие соответствие в обеих таблицах.
- LEFT JOIN оставляет каждую строку левой таблицы. Где соответствия нет, столбцы правой таблицы равны NULL.
- NULL означает, что значение отсутствует или неизвестно. Проверяйте его с помощью IS NULL, а не = NULL.
Нормализация разбивает таблицы так, чтобы каждый факт хранился один раз. Это позволяет не обновлять один и тот же факт в нескольких местах.
- 1NF: каждая ячейка содержит одно атомарное значение, без повторяющихся групп.
- 2NF: 1NF, и каждый неключевой столбец зависит от всего ключа, а не от части составного ключа.
- 3NF: 2NF, и ни один неключевой столбец не зависит от другого неключевого столбца.
Транзакция объединяет операторы в одну единицу. COMMIT делает её постоянной, а ROLLBACK отменяет. Транзакции подчиняются принципам ACID: атомарность (всё или ничего), согласованность, изолированность и долговечность.
Самопроверка У клиента нет заказов. Что происходит с этим клиентом в customers LEFT JOIN orders?
- Запрос завершается ошибкой
- Клиент исключается из результата
- Клиент появляется один раз, с NULL в столбцах заказа
- Клиент появляется по одному разу для каждого заказа в таблице
Ответ: Клиент появляется один раз, с NULL в столбцах заказа. LEFT JOIN оставляет каждую строку левой таблицы и заполняет недостающую правую часть значениями NULL. Исключение клиента — это то, что делает INNER JOIN.
4Метод по шагам
Чтобы написать запрос или выяснить, что возвращает заданный запрос:
- Найдите таблицы, содержащие данные, и то, как они связаны ключами.
- Напишите FROM с соединениями. Выберите LEFT JOIN, если строки без соответствия должны остаться.
- Добавьте WHERE для условий на отдельные строки.
- Если в вопросе есть «на каждого» или «для каждого», добавьте GROUP BY и агрегат.
- Добавьте HAVING для условий на агрегат, затем ORDER BY, если важен порядок.
- Проверьте результат на небольшом примере: перечислите строки после каждого предложения в порядке, в котором их выполняет база данных.
Для теоретического вопроса сначала назовите понятие (ключ, тип соединения, нормальная форма, свойство ACID), затем выберите вариант, соответствующий его определению.
5Разобранный пример
Пройдите каждый шаг. Попробуйте предсказать следующий, прежде чем открыть его.
Разобранный примерВ таблице customers строки (1, Ana), (2, Ben) и (3, Cas). В таблице orders строки (id, customer_id) = (10, 1), (11, 1), (12, 2) и (13, 1). Что возвращает этот запрос? SELECT c.name, COUNT(o.id) FROM customers c LEFT JOIN orders o ON o.customer_id = c.id GROUP BY c.name
1Каждый клиент сопоставляется с заказами, несущими его id. Ana соответствует заказам 10, 11 и 13. Ben соответствует заказ 12.
У Cas нет заказов. Поскольку это LEFT JOIN, Cas остаётся в результате, с NULL для o.id.
2- Ana, 10
- Ana, 11
- Ana, 13
- Ben, 12
- Cas, NULL
Это 5 строк.
3GROUP BY c.name создаёт три группы: Ana с 3 строками, Ben с 1 строкой и Cas с 1 строкой.
4COUNT(o.id) считает только значения, не равные NULL. У Ana получается 3, у Ben — 1.
У Cas одна строка, но её o.id равен NULL, поэтому у Cas получается 0.
5Ana, Ben и Cas вместе имеют 3 + 1 + 0 = 4 заказа, что совпадает с числом строк в orders. Если бы вместо этого было COUNT(*), Cas ошибочно получил бы 1, потому что COUNT(*) считает саму строку.
Ответ Ana 3, Ben 1, Cas 0.
6Типичные ошибки
- Использовать агрегат в WHERE. Условия на COUNT, SUM или AVG следует писать в HAVING.
- Писать = NULL. Любое сравнение с NULL даёт неопределённость; используйте IS NULL или IS NOT NULL.
- Использовать INNER JOIN, когда строки без соответствия должны остаться. Используйте LEFT JOIN.
- Забыть условие соединения. Без ON каждая строка сопоставляется с каждой строкой (перекрёстное соединение).
- Выбирать столбец, которого нет ни в GROUP BY, ни внутри агрегата.
- Путать DELETE (удаляет строки) и DROP TABLE (удаляет всю таблицу).
- Выполнять UPDATE или DELETE без WHERE. Это изменяет каждую строку таблицы.
Самопроверка В таблице 10 строк, и столбец col равен NULL в каждой строке. Что возвращает SELECT COUNT(col)?
- 0
- 10
- 1
- NULL
Ответ: 0. COUNT(col) считает только значения, не равные NULL, поэтому возвращает 0. COUNT(*) считает строки и вернул бы 10.
7Как выглядят экзаменационные задачи
- Лёгкая: ключевые термины и факты. Что делают SELECT, WHERE, ORDER BY или DELETE, первичные и внешние ключи, что означает NULL.
- Средняя: применение понятий. Правильный запрос для задачи, WHERE и HAVING, внутренние и внешние соединения, нормальные формы, ACID.
- Сложная: случаи и анализ. Подзапросы, уровни изоляции и их аномалии, BCNF, оконные функции, индексы и производительность запросов, SQL-инъекции.
Когда дан запрос, проследите его на нескольких строках в порядке FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY. Большинство ловушек проявляется уже на трёх строках.
Изучайте шаг за шагом в приложенииИзучайте шаг за шагом в приложении