Типы данных в SQL — что нужно знать аналитику

Зачем аналитику знать типы данных

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

Числовые типы

Тип Размер Диапазон / точность Когда использовать
INTEGER (INT) 4 байта от −2,1 млрд до 2,1 млрд id, количество, счётчики
BIGINT 8 байт до ±9,2 × 10¹⁸ id в больших таблицах, Unix-таймстемпы
NUMERIC(p, s) / DECIMAL переменный точная арифметика деньги, проценты, финансовые расчёты
FLOAT / REAL / DOUBLE PRECISION 4–8 байт приблизительная арифметика научные расчёты, метрики, где мелкие погрешности допустимы

Главное правило: для денег и финансовых данных — всегда NUMERIC. FLOAT хранит числа приблизительно: 0.1 + 0.2 может дать 0.30000000000000004. В аналитике это обычно некритично, но в отчёте по выручке — недопустимо.

Ловушка: целочисленное деление

Это самый частый сюрприз для начинающих:

SELECT 5 / 2;        -- 2, а не 2.5!
SELECT 5 / 2.0;      -- 2.5
SELECT 5::NUMERIC / 2; -- 2.5

Если оба операнда — целые числа, PostgreSQL возвращает целое число. Дробная часть просто отбрасывается. Чтобы получить дробный результат, приведите хотя бы один операнд к NUMERIC или FLOAT.

Типичная ошибка в аналитике — считать конверсию без приведения типов:

-- Неправильно: 100 / 500 = 0
SELECT COUNT(*) FILTER (WHERE paid) / COUNT(*) AS conversion
FROM users;

-- Правильно: приводим к NUMERIC
SELECT COUNT(*) FILTER (WHERE paid)::NUMERIC / COUNT(*) AS conversion
FROM users;

Строковые типы

Тип Особенность
VARCHAR(n) Строка переменной длины, максимум n символов
TEXT Строка без ограничения длины
CHAR(n) Строка фиксированной длины, дополняется пробелами

В PostgreSQL разницы в производительности между VARCHAR и TEXT нет. CHAR(n) на практике почти не используется — он дополняет значение пробелами до нужной длины, что создаёт путаницу при сравнениях. В аналитических таблицах чаще всего встретите TEXT или VARCHAR.

Дата и время

Тип Пример Когда использовать
DATE 2026-04-08 Дата рождения, отчётный период
TIMESTAMP 2026-04-08 14:30:00 Время без привязки к часовому поясу
TIMESTAMPTZ 2026-04-08 14:30:00+03 События, логи, created_at
INTERVAL INTERVAL '3 days 2 hours' Разница между датами, арифметика

Для событий — всегда TIMESTAMPTZ. Он хранит момент времени однозначно, независимо от часового пояса сервера. Если таблица событий использует TIMESTAMP без часового пояса — это потенциальная проблема: при переезде на другой сервер время «сдвинется». Подробнее о работе с датами — в отдельном гайде.

BOOLEAN

Принимает значения TRUE, FALSE и NULL. В PostgreSQL можно писать сокращённо: 't', 'f', 'yes', 'no', 1, 0 — все приведутся к boolean.

SELECT * FROM users WHERE is_active;          -- TRUE
SELECT * FROM users WHERE NOT is_active;      -- FALSE
SELECT * FROM users WHERE is_active IS NULL;  -- NULL

Обратите внимание: WHERE is_active = TRUE и WHERE is_active — одно и то же, но второй вариант короче и идиоматичнее.

NULL — не тип, но важно

NULL — это не ноль и не пустая строка. Это отсутствие значения. Любая операция с NULL возвращает NULL:

SELECT 5 + NULL;          -- NULL
SELECT 'hello' || NULL;   -- NULL
SELECT NULL = NULL;       -- NULL (не TRUE!)

Для проверки на NULL используйте IS NULL / IS NOT NULL, а не = NULL. Это одна из классических ошибок, которую спрашивают на собеседованиях.

Приведение типов (CAST)

Два способа привести тип в PostgreSQL:

-- Стандартный SQL
SELECT CAST('2026-04-08' AS DATE);
SELECT CAST(42 AS TEXT);

-- Сокращённый синтаксис PostgreSQL
SELECT '2026-04-08'::DATE;
SELECT 42::TEXT;

Оператор :: — специфика PostgreSQL. На собеседованиях можно использовать оба варианта, но :: встречается чаще в реальных запросах.

Неявное и явное приведение

PostgreSQL умеет приводить типы автоматически (неявно):

SELECT '100' + 1;   -- PostgreSQL: ошибка! Строку нельзя неявно привести к числу
SELECT 100 + 1.5;   -- 101.5, INTEGER неявно приведётся к NUMERIC

Если PostgreSQL не может привести тип автоматически — будет ошибка. Правило простое: не надейтесь на неявное приведение, приводите явно через :: или CAST.

Вопросы с собеседований

Чем NUMERIC отличается от FLOAT? — NUMERIC хранит числа точно, с заданным количеством знаков. FLOAT — приблизительно, с плавающей точкой. Для финансовых расчётов — NUMERIC, для метрик, где мелкая погрешность допустима — FLOAT.

Что вернёт SELECT 5 / 2? — Число 2. Оба операнда — INTEGER, результат тоже INTEGER, дробная часть отбрасывается. Чтобы получить 2.5, нужно привести один из операндов: 5::NUMERIC / 2 или 5 / 2.0.

Как проверить значение на NULL? — Только через IS NULL / IS NOT NULL. Оператор = с NULL всегда возвращает NULL, не TRUE. WHERE col = NULL не вернёт ни одной строки — это частая ошибка.

Чем VARCHAR отличается от TEXT в PostgreSQL? — Функционально — почти ничем. VARCHAR(n) ограничивает длину строки до n символов, TEXT — нет. Производительность одинаковая. В аналитике обычно используют TEXT.

Зачем нужен TIMESTAMPTZ вместо TIMESTAMP? — TIMESTAMPTZ хранит момент времени однозначно, с учётом часового пояса. TIMESTAMP без зоны зависит от настроек сервера — при смене сервера или зоны сессии значение интерпретируется иначе. Для событий (created_at, logged_at) — всегда TIMESTAMPTZ.

Потренируйтесь

Типы данных лучше всего запоминаются на практике — когда пишешь запросы и разбираешься, почему конверсия вышла 0 вместо 0.15. Откройте тренажёр с 1500+ вопросами по SQL и другим темам для аналитика.

FAQ

Какой тип выбрать для id — INTEGER или BIGINT?

Для небольших таблиц (до 2 млрд строк) хватит INTEGER. Для таблиц событий, логов и всего, что быстро растёт — BIGINT. В современных системах часто сразу используют BIGINT для id: разница в размере минимальна, а проблемы с переполнением исключены.

Можно ли хранить числа в VARCHAR?

Технически — да. Практически — не стоит. Вы не сможете нормально сортировать ('9' > '10' потому что строковое сравнение), не сможете складывать без приведения, займёте больше места. Числа — в числовые типы.

Что будет, если вставить строку длиннее VARCHAR(n)?

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


Больше теории и практики по SQL — в тренажёре Карьерника. 1500+ вопросов с объяснениями — на странице примеров.