JavaRush /Курсы /SQL SELF /Сравнение и преобразование типов данных

Сравнение и преобразование типов данных

SQL SELF
16 уровень , 3 лекция
Открыта

Зачем вообще всё это нужно — сравнение и преобразование типов? Представьте, у вас в таблице лежит строка "42", а вы хотите сравнить её с числом 42. На первый взгляд — одно и то же. Но для базы данных это могут быть совершенно разные вещи. PostgreSQL не будет автоматически догадываться, что вы имели в виду. И если не понимать, как именно он сравнивает значения разных типов, можно получить странный результат или вообще ошибку.

То же самое касается преобразований. Иногда нужно превратить текст в число, чтобы посчитать, сколько всего штук чего-то там. А бывает, наоборот — число нужно красиво отобразить как строку. Или взять дату и вывести её в виде "01.01.2025", потому что так привычнее пользователю.

Или вот другой пример: у вас точное значение хранится в NUMERIC, но для научных вычислений нужно использовать FLOAT. В таких случаях без явного преобразования — никуда.

Хорошая новость в том, что PostgreSQL отлично с этим справляется. Он даёт гибкие и понятные инструменты для таких задач. Главное — знать, как ими пользоваться, и не бояться немного заглянуть под капот. Этим и займёмся.

Сравнение типов данных

PostgreSQL старается быть умным — если видит, что сравниваются, скажем, INTEGER и NUMERIC, он спокойно приведёт их к общему знаменателю и всё сравнит. Это нормально, ведь оба — числа.

Но вот если вы решите сравнить строку с булевым значением (TEXT и BOOLEAN), база данных уже не поймёт, чего вы от неё хотите. У этих типов совершенно разная природа, и PostgreSQL просто выдаст ошибку. То же самое произойдёт, если вы попробуете сравнить строку "42" с числом 42, не указав явно, что хотите эту строку превратить в число.

Как это выглядит на практике? Вот пример, который вызовет ошибку:

SELECT '42' = 42; -- Ошибка! Строка и число без преобразования не сравниваются

А вот так всё сработает как надо:

SELECT '42'::INTEGER = 42; -- TRUE

Здесь мы явно говорим: “Пожалуйста, сначала преврати '42' в число”. Для этого и нужен синтаксис ::Тип, о котором мы уже упоминали. PostgreSQL любит, когда с ним разговаривают чётко.

Сравнение числовых типов

Числовые типы данных (INTEGER, NUMERIC, REAL) чаще всего совместимы между собой, поэтому их можно сравнивать без особых сложностей:

SELECT 42 = 42.0; -- TRUE
SELECT 42::REAL = 42.0; -- TRUE
SELECT 42.0::NUMERIC = 42; -- TRUE

Однако будьте осторожны с числами с плавающей запятой (REAL). Из-за ограниченной точности такие числа могут вести себя неожиданно. Например:

SELECT 0.1 + 0.2 = 0.3; -- FALSE

Разве это не самая известная загадка программирования? Здесь сравнение возвращает FALSE из-за особенностей хранения дробных чисел в памяти компьютера.

Сравнение текстовых типов

При работе с текстовыми типами вы можете сравнивать CHAR, VARCHAR и TEXT, так как PostgreSQL автоматически преобразует их к совместимым типам:

SELECT 'Hello' = 'Hello'::TEXT; -- TRUE
SELECT 'World'::CHAR(5) = 'World'::VARCHAR; -- TRUE

Обратите внимание на длину символов в CHAR(n): если строка короче указанной длины, PostgreSQL дополнит её пробелами.

Преобразование типов данных

PostgreSQL предоставляет несколько способов преобразования типов данных. Мы разберем два основных метода:

Способ №1: Явное преобразование (CAST)

Оператор CAST позволяет определить, как нужно преобразовать один тип в другой. Вот пример:

SELECT CAST('42' AS INTEGER); -- Преобразует строку '42' в число 42

Этот метод особенно удобен, если вы хотите сделать SQL-код более читаемым.

Способ №2: Сокращенная запись (::)

PostgreSQL предлагает альтернативный синтаксис для преобразования типов — использование ::. Это та же операция, но записана более кратко:

SELECT '42'::INTEGER; -- То же самое, что и CAST('42' AS INTEGER)

Автоматическое преобразование

Во многих случаях PostgreSQL автоматически преобразует данные. Например, использование чисел в строковых полях:

SELECT '42' = 42::TEXT; -- TRUE

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

Примеры преобразования разных типов данных

Преобразование чисел в текст

Иногда возникает необходимость преобразовать числа в текст (например, для формирования сообщений):

SELECT 42::TEXT; -- Преобразует число 42 в строку '42'
SELECT 3.14::TEXT; -- Преобразует число 3.14 в строку '3.14'

Преобразование текста в числа

Если в строке содержится корректное число, вы можете преобразовать её в числовой тип:

SELECT '123'::INTEGER; -- Преобразует строку '123' в число 123
SELECT '3.14'::FLOAT;  -- Преобразует строку '3.14' в число 3.14

Но что будет, если текст не поддается преобразованию? Например:

SELECT 'Hello'::INTEGER; -- Ошибка: невозможно преобразовать 'Hello' в число

Чтобы избежать таких ошибок, вы можете использовать функцию TRY_CAST() (начиная с PostgreSQL 14) или предварительно проверять данные.

Преобразование даты в текст и обратно

При преобразовании дат вы можете использовать функции TO_CHAR() и TO_DATE():

SELECT TO_CHAR(CURRENT_DATE, 'YYYY-MM-DD'); -- Преобразует дату в строку
SELECT TO_DATE('2023-10-25', 'YYYY-MM-DD'); -- Преобразует строку в дату

Преобразование между BOOLEAN и текстом

Логический тип данных BOOLEAN также можно преобразовывать в строки:

SELECT TRUE::TEXT; -- 'true'
SELECT FALSE::TEXT; -- 'false'

Или наоборот:

SELECT 'true'::BOOLEAN; -- TRUE
SELECT 'false'::BOOLEAN; -- FALSE

Обратите внимание, что строки вроде 'yes' или 'no' не будут преобразованы автоматически.

Практика: всё на реальных примерах

Создадим таблицу, которая демонстрирует использование разных типов данных:

id number_as_text - TEXT number_as_integer - INTEGER date_as_text - TEXT actual_date - DATE
1 42 42 2023-10-25 2023-10-25
2 3.14 NULL 2023-10-24 NULL
3 Hello 123 NULL NULL

Теперь выполним операции преобразования:

-- Преобразование текста в число
SELECT number_as_text::INTEGER FROM data_types_demo WHERE number_as_text = '42';

-- Преобразование даты в текст
SELECT TO_CHAR(actual_date, 'DD/MM/YYYY') FROM data_types_demo;

-- Преобразование строки в дату
SELECT TO_DATE(date_as_text, 'YYYY-MM-DD') FROM data_types_demo;

Типичные ошибки при преобразовании данных

Типичные ошибки включают:

  1. Попытки преобразовать данные, которые не соответствуют ожидаемому формату (например, строку 'Hello' в INTEGER).
  2. Проблемы с округлением и точностью при работе с числами с плавающей запятой.
  3. Некорректное использование форматов при преобразовании дат.

Для предотвращения ошибок рекомендуется:

  • Всегда проверять данные перед преобразованием.
  • Использовать функции обработки ошибок (TRY_CAST или CASE).
  • Указывать формат явно при преобразовании дат.
-- Проверка данных перед преобразованием
SELECT 
    CASE 
        WHEN number_as_text ~ '^\d+$' THEN number_as_text::INTEGER
        ELSE NULL
    END AS safe_integer
FROM data_types_demo;

Используйте этот подход, чтобы защитить ваши запросы от неожиданных ситуаций!

На этом этапе вы обладаете базовыми навыками для сравнения и преобразования типов данных в PostgreSQL. Остается только практика, практика и ещё раз практика. Увидимся на следующих лекциях!

2
Задача
SQL SELF, 16 уровень, 3 лекция
Недоступна
Преобразование строкового значения в число
Преобразование строкового значения в число
2
Задача
SQL SELF, 16 уровень, 3 лекция
Недоступна
Преобразование дат
Преобразование дат
Комментарии (4)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Alexandr Уровень 16
18 ноября 2025
Если целевая СУБД — SQLite, замените TO_DATE на подходящую функцию (например, date(substr(event_date,7,4)||'-'||substr(event_date,4,2)||'-'||substr(event_date,1,2))). Если требуется совместимость с SQLite, используйте выражение: date(substr(event_date,7,4)||'-'||substr(event_date,4,2)||'-'||substr(event_date,1,2))
28 июня 2025
Создадим таблицу, которая демонстрирует использование разных типов данных:

id 	numberastext - TEXT 	numberasinteger - INTEGER 	dateastext - TEXT 	actual_date - DATE
Отсутствует подчеркивание, и такие мелочевки во многих лекциях, а надо

id 	number_as_text - TEXT 	number_asi_nteger - INTEGER 	date_as_text - TEXT 	actual_date - DATE
28 июня 2025
Чтобы избежать таких ошибок, вы можете использовать функцию TRY_CAST() (начиная с PostgreSQL 14) или предварительно проверять данные. В PostgreSQL такой функции нет, это есть в SQL Server
Юрий Уровень 60
14 июля 2025
Это вот совсем косяк.