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;       -- 0

JSON / 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.5

2. Precision loss

SELECT 1000000000000::INTEGER;  -- overflow!
SELECT 1000000000000::BIGINT;   -- OK

3. 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 нет.