Текст и даты: varchar, text, timestamp, interval

Храним строки и работаем со временем — двумя типами данных, которые есть в каждой таблице.

timestamp with time zone (timestamptz) — тип для момента времени, который PostgreSQL хранит в UTC и корректно сравнивает между часовыми поясами.

Строки: varchar, char, text

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

ТипКогда брать
varchar(n)строка с ограничением длины (например, код страны varchar(2))
textстрока любой длины — в PostgreSQL это самый частый выбор
char(n)строка фиксированной длины, дополняется пробелами; используется редко

Важная особенность PostgreSQL: text и varchar работают одинаково быстро. Ограничение длины — это про валидацию данных, а не про производительность. Если ограничение не нужно, смело берите text.

Дата и время

Типов для времени несколько, и путать их опасно.

ТипЧто хранит
dateтолько дату: 2026-06-14
timeтолько время суток: 14:30:00
timestampдату и время без часового пояса
timestamptzмомент времени с учётом пояса (хранится в UTC)
intervalпромежуток: «3 дня», «2 часа 30 минут»

Практическое правило: для событий («когда создан заказ», «время входа») почти всегда берите timestamptz. Он избавляет от боли с часовыми поясами: что бы вы ни вставили, внутри хранится UTC, а на вывод приводится к поясу сессии.

Арифметика дат и interval

Со временем в PostgreSQL можно складывать и вычитать. Разность двух дат даёт interval, а к дате можно прибавить интервал.

-- Текущий момент
SELECT now();

-- Через сколько истечёт подписка на 30 дней
SELECT now() + INTERVAL '30 days' AS expires_at;

-- Сколько дней между двумя датами
SELECT DATE '2026-06-14' - DATE '2026-06-01' AS days;  -- 13

now() возвращает текущий момент как timestamptz. Конструкция INTERVAL '30 days' читается как естественный язык — можно писать '2 hours', '1 year 6 months' и так далее.

Практика: фильтр по дате в песочнице

Даты как строки в формате ГГГГ-ММ-ДД отлично сортируются и сравниваются. Переносимый пример — запустите и поменяйте границу.

CREATE TABLE events (
    id    INTEGER PRIMARY KEY,
    title TEXT,
    day   TEXT
);

INSERT INTO events (id, title, day) VALUES
    (1, 'Релиз',       '2026-03-01'),
    (2, 'Конференция', '2026-06-10'),
    (3, 'Ретро',       '2026-06-20');

SELECT title, day
FROM events
WHERE day >= '2026-06-01'
ORDER BY day;

Вывод:

Конференция|2026-06-10
Ретро|2026-06-20

Формат ГГГГ-ММ-ДД удобен тем, что лексикографический порядок строк совпадает с хронологическим. В реальном PostgreSQL для этого столбца, конечно, лучше тип date, но логика сравнения та же.

Итог

  • Для строк по умолчанию берите text; varchar(n) — когда нужно ограничить длину.
  • timestamptz — лучший выбор для моментов времени, он хранит UTC и спасает от путаницы с поясами.
  • Разность дат даёт interval; к дате можно прибавлять INTERVAL '...'.
Проверьте себя
1. Какой строковый тип чаще всего используют в PostgreSQL, когда ограничение длины не нужно?
Achar(n)
Btext
Cvarchar(1)
Dblob
2. Почему для моментов времени рекомендуют timestamptz?
AОн занимает меньше места
BОн хранит время в UTC и корректно сравнивается между часовыми поясами
CОн быстрее любого другого типа
DОн единственный поддерживает даты
3. Что вернёт выражение DATE '2026-06-14' - DATE '2026-06-01'?
AДату
BИнтервал в 13 дней
CОшибку
DСтроку '13'
Поддержать проект