Раздел 33 · PostgreSQL с нуля

Создание базы, таблицы и GUI-клиенты

junior~20 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке мы смотрели на то, что уже лежит в кластере. Пора положить туда своё. Сквозной пример раздела это книжный интернет-магазин: книги, покупатели, заказы. Сегодня заводим под него базу и первую таблицу, разбираемся, где она окажется, и открываем ту же базу в графическом клиенте.

Здание, этаж, комната, шкаф

Чтобы найти документ в большом офисе, нужен полный адрес: здание, этаж, комната, шкаф. В PostgreSQL у каждой таблицы тоже есть адрес из четырёх уровней:

кластер (сервер)              здание
└── база данных bookshop      этаж
    └── схема public          комната
        └── таблица books     шкаф

Про кластер мы уже знаем: это запущенный сервер со всеми базами. Две новые ступени, база и схема, похожи друг на друга, но ведут себя по-разному.

База данных это этаж с отдельным входом. Подключаешься всегда к одной базе, и запрос не может напрямую взять таблицу с соседнего этажа. Обычно одна база на одно приложение.

Схема это комната на этаже. Двери между комнатами открыты: в одном запросе можно взять таблицы из разных схем, если указать полный адрес схема.таблица. Схемы помогают разложить таблицы большого приложения по смыслу, например billing и catalog.

Создаём базу

Подключись к кластеру через psql, как в прошлых уроках, и выполни:

CREATE DATABASE bookshop;
CREATE DATABASE

Новая база копируется с заготовки template1, так что сразу после создания она пустая, но уже со схемой public. Переключаемся в неё:

postgres=# \c bookshop
You are now connected to database "bookshop" as user "postgres".
bookshop=#

Две особенности, о которые спотыкаются.

Во-первых, CREATE DATABASE одно из немногих исключений из транзакционного DDL. Его нельзя выполнить внутри транзакции:

ERROR:  CREATE DATABASE cannot run inside a transaction block

Во-вторых, база с таким именем может уже существовать, и тогда сервер откажет:

ERROR:  database "bookshop" already exists

Базу удаляет команда DROP DATABASE bookshop;. Подтверждения не будет, восстановить данные потом можно только из резервной копии. Поэтому перед DROP всегда смотри на приглашение psql и проверяй, в какой кластер ты подключён.

Схема public и путь поиска

Создадим первую таблицу:

CREATE TABLE books (
  id     integer PRIMARY KEY,
  title  text    NOT NULL,
  author text    NOT NULL,
  price  numeric(8, 2)
);

Схему мы не указали, а таблица всё равно куда-то попала. \dt покажет public | books. Почему public? Сервер ищет схему по списку, который называется search_path:

SHOW search_path;
   search_path
-----------------
 "$user", public
(1 row)

Сначала сервер ищет схему с именем текущего пользователя. Такой у нас нет, поэтому берётся следующая, public. В неё же попадают новые таблицы без явной схемы.

Если таблица лежит в схеме вне этого списка, по короткому имени её не найти:

CREATE SCHEMA warehouse;
CREATE TABLE warehouse.stock (book_id integer, qty integer);

SELECT * FROM stock;
ERROR:  relation "stock" does not exist

SELECT * FROM warehouse.stock работает. Для новичкового проекта хватает одной схемы public, и в этом разделе мы почти всегда будем работать в ней.

Слово relation в ошибке значит «таблица или что-то похожее на неё». Название пришло из реляционной модели, где таблица называется отношением.

урок из курса

Урок из курса «PostgreSQL с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.