Навіщо взагалі все це потрібно — порівняння та перетворення типів? Уяви, у тебе в таблиці лежить рядок "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;
Типові помилки при перетворенні даних
Типові помилки включають:
- Спроби перетворити дані, які не відповідають очікуваному формату (наприклад, рядок
'Hello'уINTEGER). - Проблеми з округленням і точністю при роботі з числами з плаваючою комою.
- Некоректне використання форматів при перетворенні дат.
Щоб уникнути помилок, рекомендується:
- Завжди перевіряти дані перед перетворенням.
- Використовувати функції обробки помилок (
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. Далі — тільки практика, практика і ще раз практика. Побачимось на наступних лекціях!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ