Это теоретический фундамент курса. Если формулы реляционной алгебры покажутся тяжёлыми — это нормально: ты уже умеешь делать запросы из модуля 1. К теории всегда можно вернуться позже, когда практики станет больше.
Зачем начинать с теории
SQL придумали не с потолка. В 1970 году Эдгар Кодд опубликовал работу
Это объясняет 80% странностей языка: почему NULL != NULL, почему SELECT * возвращает строки в произвольном порядке, почему DISTINCT бесплатен в теории, но дорог на практике. Все эти ответы выводятся из того, чем именно отношение отличается от обычной таблицы, которую вы привыкли видеть в Excel.
Реляция — это не таблица
Формально, отношение (relation) — это множество кортежей, в котором все кортежи имеют одну и ту же схему.
- Кортеж () — это набор пар «имя атрибута → значение». В SQL это одна строка.tuple
- Схема — список атрибутов с их типами. В SQL это
CREATE TABLE. - Атрибут — одно поле кортежа. В SQL это столбец.
- Множество — совокупность без повторов и без порядка.
Последнее слово — ключевое. Именно «множество» отделяет реляцию от Excel-таблицы.
Слева — то, что вы привыкли видеть. Справа — формальный объект реляционной модели.
Из этого определения вытекают четыре свойства, которые отличают реляцию от любой Excel-таблицы:
- Дубликаты невозможны — два одинаковых кортежа в множестве это один кортеж.
- Порядок строк не определён — множество не упорядочено. Любой запрос без
ORDER BYможет вернуть строки в произвольном порядке, и это не баг, это определение. - Порядок атрибутов фиксирован схемой, но обращение к ним идёт по имени, а не по позиции.
- Значения атомарны — никаких вложенных таблиц внутри ячеек. Это правило 1-й нормальной формы (1NF), сам Кодд называл его «свойство first-normal-form».
В реальном PostgreSQL первое правило размыто: CREATE TABLE по умолчанию создаёт не «чистое» отношение, а мультимножество (bag) — туда можно вставить две одинаковые строки. Чтобы получить настоящее множество, нужны явные UNIQUE ограничения. Это уступка практике: уникальность стоит дорого, а в большинстве задач она не нужна.
Посмотрим на это руками
Через весь курс мы будем работать с одной и той же вселенной — крошечным e-commerce: таблицы customers, categories, products, orders, order_items. Эта схема уже загружена в каждую песочницу под этим уроком; не нужно ничего создавать, можно сразу писать запросы.
Песочница ниже запускает настоящий PostgreSQL прямо в браузере — никакого сервера. Можешь править запрос и нажимать «Запустить» сколько угодно раз.
Выбираем все кортежи из отношения customers:
Обрати внимание: порядок строк, который ты видишь, не гарантирован стандартом SQL. PostgreSQL в этом конкретном запросе обычно возвращает их в порядке вставки, но это деталь реализации — на больших таблицах, после UPDATE, после VACUUM порядок может измениться. Если порядок важен — пиши ORDER BY. Всегда.
Попробуй сам — отфильтруй только клиентов из России:
Замени запрос — выбери клиентов с country = 'RU':
Почему NULL != NULL
Раз уж зашла речь про следствия из теории — вот первое классическое.
В реляционной модели атрибут — это пара «имя → значение». А что, если значения нет? Кодд ввёл специальный маркер NULL, означающий «значение неизвестно». Это не пустая строка, не ноль и не «ничего». Это «может быть что угодно — мы не знаем».
Из этой семантики следует невероятное на первый взгляд правило: сравнение NULL = NULL возвращает не TRUE, а сам NULL. Потому что «неизвестное равно неизвестному» — это тоже неизвестно. Мы не можем утверждать, что эти два неизвестных значения совпадают.
Посмотри на трёхзначную логику NULL:
Колонка equal_to_null будет NULL, не true и не false. Это трёхзначная логика SQL: каждый предикат может вернуть true, false или NULL. Когда ты пишешь WHERE x = NULL — фильтр всегда отсеивает строку, потому что результат NULL не считается «истиной». Чтобы проверить отсутствие значения, используй IS NULL.
Это видно прямо в нашей таблице: у клиентки с email [email protected] поле birth_year равно NULL. Попробуй выбрать всех клиентов с неизвестным годом рождения:
Найди клиентов с birth_year = NULL — внимательно, у вопроса есть подвох:
Мы вернёмся к NULL и трёхзначной логике плотнее в модуле «Типы данных и NULL-семантика». Сейчас важно запомнить: это не баг и не уродство — это вывод из определения реляции и атрибута.
Что дальше
В следующих уроках мы пройдём по основным операциям реляционной алгебры — селекции (σ), проекции (π), декартову произведению и соединениям. Это даст инструментарий из шести операций, через которые выражаются почти все SQL-запросы. Когда ты увидишь сложный запрос на 200 строк и потеряешься — всегда можно разложить его на эти шесть кирпичей.
А пока — главный итог этого урока:
- Реляция — это множество кортежей, а не таблица в Excel.
- Дубликаты в чистом отношении невозможны, порядок не определён, значения атомарны.
- PostgreSQL расширяет это до мультимножества по умолчанию (можно
INSERTдубликаты) — это компромисс ради производительности. - Все «странности» SQL —
NULL-семантика, отсутствие гарантии порядка, бесплатностьDISTINCTв теории — это прямые следствия определения.