Введение
Основной цикл статей уже касался SQL точечно (статья 12 — базовый SQL, статьи 230-239 — БД/ORM с Qt), но без систематического, последовательного разбора самого языка и реляционной модели как таковой. Этот расширенный SQL-цикл из 50 статей закрывает этот пробел — начинаем с фундамента: что такое реляционная модель данных и из каких элементов она состоит, независимо от конкретной СУБД.
Концепция
Реляционная модель организует данные в таблицы (relations) — каждая таблица состоит из строк (rows/tuples, отдельных записей) и столбцов (columns/attributes, определяющих, какие именно данные хранятся в каждой записи и какого они типа). Каждая строка таблицы должна быть однозначно идентифицируема — для этого используется первичный ключ (primary key, статья 397), а связи между разными таблицами (например, между «заказами» и «клиентами») выражаются через внешние ключи (foreign keys), а не через произвольное вложение данных одной записи в другую, как это могло бы быть в документ-ориентированной модели (статья 440).
Пример кода: Реляционная модель данных
-- Простейшая таблица — структура задаёт имена и типы столбцов
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
registered_at DATE
);
-- Строка таблицы — конкретный набор значений, соответствующих структуре столбцов
INSERT INTO customers (id, name, email, registered_at)
VALUES (1, 'Иван Петров', 'ivan@example.com', '2026-01-15');
-- Связанная таблица — внешний ключ customer_id ссылается на customers.id
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER REFERENCES customers(id),
total_amount DECIMAL(10, 2),
order_date DATE
);
INSERT INTO orders (id, customer_id, total_amount, order_date)
VALUES (101, 1, 1500.00, '2026-02-01');
Пояснения к коду
Таблица customers объявляет фиксированную структуру — любая строка, добавленная в эту таблицу, обязана соответствовать этой структуре (иметь значения нужных типов для каждого столбца, кроме допускающих NULL), что принципиально отличается от свободной, гибкой по структуре каждой отдельной записи модели документ-ориентированных БД. Связь между orders и customers устанавливается через customer_id INTEGER REFERENCES customers(id) — это и есть внешний ключ, гарантирующий (через ограничение целостности, обеспечиваемое самой СУБД), что значение customer_id в любой строке orders соответствует реально существующей строке в customers, а не произвольному, возможно «осиротевшему» значению.
Подводные камни
- Хранение нескольких значений в одном столбце через разделитель (например, столбец
tags VARCHAR(255)со значением"спорт,музыка,кино") вместо вынесения этих значений в отдельную, связанную таблицу — это нарушает базовый принцип реляционной модели (атомарность значений столбца) и делает невозможным эффективный поиск/фильтрацию по отдельным значениям без текстового парсинга строки на стороне приложения; такие случаи разбираются подробнее в контексте нормализации (статья 402). - Путаница между логической структурой данных (таблицы реляционной модели) и физическим способом их хранения на диске — реляционная модель описывает, как данные организованы логически, но не диктует напрямую, как именно СУБД физически размещает их на диске (это решает конкретная реализация конкретной СУБД, статьи 423-426); разработчику в большинстве случаев достаточно мыслить на уровне логической модели, не вникая в детали физического хранения, кроме случаев специальной оптимизации производительности (блок 3 цикла).
- Проектирование таблиц без заранее продуманных первичных ключей, понадеявшись добавить их позже — для таблиц с уже накопленными данными добавление первичного ключа постфактум может натолкнуться на дублирующиеся значения, отсутствовавшие при первоначальном, менее строгом проектировании, что потребует дополнительной очистки данных перед тем, как ограничение первичного ключа можно будет успешно применить.
- Игнорирование типов данных столбцов и хранение всего как текстовых строк «для простоты» — хранение чисел или дат как
VARCHARлишает СУБД возможности проверять корректность значений на уровне ограничений (нельзя вставить «abc» в числовой столбец, но можно в текстовый, который «должен» содержать число только по соглашению), и теряет эффективность сравнения/сортировки, оптимизированную СУБД именно для правильных, специализированных типов данных.