PostgreSQL · Урок 1
Самый первый кирпич. Через 15 минут у вас будет настоящая таблица в PostgreSQL, заполненная вашими данными — и понимание, что́ под ней лежит.
Зачем это для вашей миссии: и чтобы проектировать свои базы, и чтобы читать чужие — всё начинается с таблицы. Не поняв её устройство, нельзя осмысленно говорить ни о ключах, ни об индексах. Это фундамент, на который встанут все следующие уроки.
Если вы программист, у вас уже есть нужная аналогия. Таблица — это типизированный список записей.
title: string, year: int).Разница с обычным массивом объектов в коде: таблица живёт в базе, переживает перезапуск программы, и СУБД заставляет соблюдать типы и правила — положить текст в числовой столбец просто не получится.
Вот как таблица books выглядит «на бумаге»:
| title text | author text | year integer | read boolean |
|---|---|---|---|
| Чистый код | Роберт Мартин | 2008 | true |
| SQL за 10 минут | Бен Форта | 2019 | false |
| Сказки | Народное | NULL | false |
Шапка задаёт столбцы и их типы (это схема). Каждая строка — одна книга. У «Сказок» год неизвестен — там стоит NULL.
У каждого столбца ровно один тип, общий для всех строк. Это не «подсказка», как в динамических языках, — это жёсткое правило: PostgreSQL отвергнет запись, если значение не подходит под тип.[1] Базовый набор типов: integer/bigint (целые), text (строки), boolean (да/нет), date/timestamptz (даты и время), numeric (точные числа, например деньги).[2]
Таблица — это множество строк, а не упорядоченный список. У строк нет «номера по порядку» и нет гарантированного порядка хранения: пока вы не напишете ORDER BY, СУБД вправе вернуть строки в любом порядке. Это важная мысль — не полагайтесь на «порядок, в котором вставляли».
NULL означает «значения нет / неизвестно». Это не ноль и не пустая строка. Из-за этого NULL ведёт себя особенно: выражение year = NULL возвращает не «истину» и не «ложь», а «неизвестно», поэтому проверять надо через IS NULL / IS NOT NULL.[3] Запомните это сейчас — позже это спасёт от коварных багов в запросах.
Почему «множество, а не список»? Потому что в основе лежит реляционная модель: таблица = отношение, строка = кортеж. Физически же Postgres хранит строки как кортежи (tuples) в «куче» (heap) — наборе страниц по 8 КБ на диске. Когда вы вставляете строку, она просто кладётся в свободное место на какой-то странице; никакого «порядка» там нет. Адрес строки внутри файла называется TID. Из этого растут две будущие темы курса: чтобы быстро находить строку по значению, нужен индекс, а чтобы надёжно ссылаться на конкретную строку — первичный ключ.[4]
Нужен работающий PostgreSQL и клиент psql. Самый быстрый путь — Docker (одна команда поднимает сервер, вторая открывает консоль):
# поднять сервер PostgreSQL в фоне docker run --name pg-learn -e POSTGRES_PASSWORD=secret -p 5432:5432 -d postgres # открыть консоль psql внутри контейнера docker exec -it pg-learn psql -U postgres
Увидели приглашение postgres=# — вы внутри. Нет Docker под рукой? Откройте онлайн-песочницу DB Fiddle (выберите PostgreSQL) и выполняйте SQL там.
Это команда CREATE TABLE: имя таблицы, затем в скобках список «столбец тип».[1] Выполните:
CREATE TABLE books ( title text, author text, year integer, read boolean );
Ответ CREATE TABLE = успех. Посмотрите структуру командой \d books — psql покажет столбцы и типы.
Команда INSERT: какие столбцы и какие значения.[5] Текст — в одинарных кавычках, числа и true/false — без. Заметьте: у последней книги год не указан — туда попадёт NULL.
INSERT INTO books (title, author, year, read) VALUES ('Чистый код', 'Роберт Мартин', 2008, true), ('SQL за 10 минут', 'Бен Форта', 2019, false); -- без указания year — туда встанет NULL INSERT INTO books (title, author, read) VALUES ('Сказки', 'Народное', false);
Команда SELECT читает строки. * = «все столбцы».
SELECT * FROM books; -- только книги с неизвестным годом (правильная проверка NULL): SELECT title FROM books WHERE year IS NULL; -- а так — НЕ сработает (вернёт пусто), сравнение с NULL даёт «неизвестно»: SELECT title FROM books WHERE year = NULL;
Сравните два последних запроса — это и есть та самая ловушка NULL вживую.
У вас есть настоящая таблица в PostgreSQL с тремя строками, типизированными столбцами и одним NULL. Вы её создали, наполнили и прочитали. Это полный цикл DDL → DML.
Впишите ответы — они сохранятся в браузере; кнопкой «Копировать ответы» внизу пришлёте их мне на проверку.
Мгновенная обратная связь — выберите вариант, объяснение появится сразу.
1. Что лучше всего описывает столбец таблицы?
Столбец — это «поле» с фиксированным типом, общим для всех строк. Одну запись описывает строка, а не столбец.
2. В каком порядке хранятся строки таблицы?
Таблица — это множество. Без ORDER BY СУБД может вернуть строки в любом порядке. Полагаться на «порядок вставки» — частый источник багов.
3. Чему равно значение NULL в столбце year?
NULL — это «нет данных», а не 0 и не пустая строка. Поэтому и сравнивать его надо через IS NULL, а не = NULL.
4. Почему WHERE year = NULL не вернёт книгу «Сказки»?
В трёхзначной логике SQL любое сравнение = с NULL даёт результат «неизвестно». Фильтр WHERE пропускает только «истину», поэтому строка отсекается. Нужен IS NULL.
5. В нашей таблице нет столбца-идентификатора. Какая проблема из-за этого возникает?
Именно так. Если две строки совпадут во всех столбцах, адресовать «вот эту» нельзя. Это и есть мотивация следующего урока — первичный ключ.
Вы заметили: у строк нет надёжного «удостоверения личности». Если в books попадут две одинаковые строки, выбрать ровно одну будет нечем. Урок 2 — «Первичный ключ»: как дать каждой строке уникальный идентификатор и почему это меняет всё в проектировании.