CAST в SQL: шпаргалка для собеседования
Зачем аналитику преобразование типов
Типы ломают запросы: строка вместо числа, дата как строка, integer overflow. CAST — первая помощь. На собесе проверяют знание синтаксиса и ловушек.
Синтаксис
-- Стандартный
CAST('123' AS INTEGER)
CAST('2026-04-15' AS DATE)
CAST(price AS DECIMAL(10,2))
-- PostgreSQL (короче)
'123'::INTEGER
'2026-04-15'::DATE
price::NUMERIC
-- MySQL
CONVERT('123', SIGNED)Оператор :: работает в PostgreSQL и ClickHouse. В MySQL и SQL Server только CAST/CONVERT.
Основные преобразования
| Из | В | Пример |
|---|---|---|
| text | integer | '42'::int |
| integer | text | 42::text |
| text | date | '2026-04-15'::date |
| text | timestamp | '2026-04-15 10:00'::timestamp |
| integer | boolean | 1::boolean = true |
| decimal | integer | 3.9::int = 3 (обрезка, не округление) |
Безопасное преобразование
Если строка не парсится — CAST кинет ошибку:
SELECT '123abc'::INTEGER; -- ERROR!Решения:
PostgreSQL
-- NULL если не получилось
SELECT CASE
WHEN col ~ '^\d+$' THEN col::INTEGER
ELSE NULL
END FROM t;ClickHouse — встроенные OrNull
SELECT toInt32OrNull('123abc'); -- NULL
SELECT toDateOrZero('invalid'); -- '1970-01-01'BigQuery
SELECT SAFE_CAST('123abc' AS INT64); -- NULLЕсли хочется сразу закрепить тему на практике — открой тренажёр в Telegram. 10 минут в день — и синтаксис в пальцах.
Преобразование дат
-- Строка → дата
SELECT TO_DATE('15.04.2026', 'DD.MM.YYYY'); -- PostgreSQL
SELECT STR_TO_DATE('15.04.2026', '%d.%m.%Y'); -- MySQL
-- Дата → строка в формате
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD'); -- PostgreSQL
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- MySQL
-- Timestamp → дата (обрезать время)
SELECT created_at::DATE FROM orders;
-- Unix timestamp → timestamp
SELECT TO_TIMESTAMP(1714000000);Числовые касты
-- Деление: без CAST может быть integer division!
SELECT 3 / 2; -- 1 (integer!)
SELECT 3 / 2.0; -- 1.5
SELECT 3::NUMERIC / 2; -- 1.5
SELECT CAST(3 AS FLOAT) / 2; -- 1.5
-- Округление
SELECT ROUND(3.56, 1); -- 3.6
SELECT CEIL(3.1); -- 4 (вверх)
SELECT FLOOR(3.9); -- 3 (вниз)
SELECT TRUNC(3.9); -- 3 (обрезка)На собесе ловушка: «Почему SELECT 100 / 3 даёт 33, а не 33.33?» Ответ: integer division. Решение — 100.0 / 3 или CAST(100 AS NUMERIC) / 3.
Boolean касты
-- PostgreSQL: 'yes'/'no', 't'/'f', 'true'/'false', 1/0
SELECT 'yes'::BOOLEAN; -- TRUE
SELECT 1::BOOLEAN; -- TRUE
SELECT 0::BOOLEAN; -- FALSE
-- Обратно
SELECT TRUE::INT; -- 1
SELECT FALSE::INT; -- 0JSON / JSONB касты (PostgreSQL)
SELECT '{"name": "Ivan"}'::JSONB;
SELECT '{"price": 100}'::JSON->>'price'; -- '100' (string!)
SELECT ('{"price": 100}'::JSON->>'price')::INTEGER; -- 100
-- Внутри JSONB
SELECT (data->>'age')::INTEGER FROM users WHERE (data->>'age')::INT > 18;Частые ловушки
1. Integer division
SELECT 5 / 2; -- 2 (не 2.5!)
SELECT 5 * 1.0 / 2; -- 2.5
SELECT 5.0 / 2; -- 2.52. Precision loss
SELECT 1000000000000::INTEGER; -- overflow!
SELECT 1000000000000::BIGINT; -- OK3. String collation
-- '10' > '9' как строки → FALSE!
SELECT '10' > '9'; -- TRUE (лексикографически)? Нет, FALSE
SELECT '10' > '9'; -- Actually FALSE! string comparison: '1' < '9'
SELECT '10'::INT > '9'::INT; -- TRUE (правильно)4. Timezone при касте timestamp
-- Теряет timezone!
SELECT '2026-04-15 10:00:00+03'::TIMESTAMP; -- '2026-04-15 10:00:00' (локальное)
SELECT '2026-04-15 10:00:00+03'::TIMESTAMPTZ; -- сохраняет TZЧтобы не только читать теорию, но и решать реальные задачи — загляните в бот Карьерника. Там по каждой теме подборка вопросов с разборами.
10 задач на CAST
1. Число в правильном десятичном делении
SELECT revenue::NUMERIC / users::NUMERIC AS arpu FROM stats;2. Дата из строки
SELECT TO_DATE(date_str, 'YYYY-MM-DD') FROM imported_data;3. Обрезать время из timestamp
SELECT created_at::DATE FROM events;4. Год из даты
SELECT EXTRACT(YEAR FROM created_at)::INT FROM orders;5. Преобразовать текст в деньги
SELECT REPLACE(price_str, ',', '.')::NUMERIC FROM products;6. Процент как строка с %
SELECT ROUND(100 * paid::NUMERIC / total, 2) || '%' FROM stats;7. Массив из строки
SELECT STRING_TO_ARRAY('a,b,c', ',');8. Безопасный каст (если не число — NULL)
SELECT CASE WHEN col ~ '^-?\d+$' THEN col::INT ELSE NULL END FROM t;9. Unix timestamp в дату
SELECT TO_TIMESTAMP(ts_seconds) FROM logs;10. Округление до 2 знаков
SELECT ROUND(value::NUMERIC, 2) FROM stats;Как тренироваться
Преобразование типов — тема где минимум теории, максимум практики. Пишите запросы, ловите ошибки division by zero, invalid input syntax, numeric field overflow — и запоминаете на всю жизнь.
Тренажёр Карьерник содержит блок на CAST и преобразования — с разборами типичных ловушек.
Совет: при делении целых всегда умножайте на 1.0 или кастуйте в NUMERIC. Это защита от integer division и первая проверка, которую делают интервьюеры.
Читайте также
FAQ
CAST или ::?
Функционально одинаково в PostgreSQL. CAST — SQL-стандарт, работает везде. :: — короче, только PostgreSQL и ClickHouse. На собесе знайте оба.
Почему integer / integer даёт integer?
Это поведение большинства СУБД по стандарту SQL. Если оба операнда INTEGER — результат INTEGER. Решение: кастовать хотя бы один в NUMERIC/FLOAT.
Что быстрее — CAST или SUBSTRING + CAST?
CAST всегда. Сложные операции (SUBSTRING, REGEXP_REPLACE) медленнее прямого CAST. Если данные «правильные» — просто кастуйте.
Как обработать неправильные значения в касте?
В PostgreSQL — через CASE + регулярки. В ClickHouse — через toInt32OrNull, toDateOrZero. В BigQuery — через SAFE_CAST. Универсального способа в стандартном SQL нет.