Пошук уроків, статей та іншого контенту
Ознайомитеся з базовими, числовими, текстовими, логічними та спеціалізованими типами даних PostgreSQL.
Тип даних визначає, які значення може зберігати стовпець таблиці та як PostgreSQL працюватиме з цими значеннями.
Наприклад:
integer зберігає цілі числа;
text — текст;
boolean — true або false;
date — календарну дату.
Правильно вибраний тип допомагає:
зберігати лише коректні значення;
економити місце;
виконувати точні обчислення;
ефективніше шукати й сортувати дані.
Тип стовпця задають під час створення таблиці:
CREATE TABLE users (
id integer,
name text,
is_active boolean
);У цій таблиці:
id може містити цілі числа;
name — текст;
is_active — логічне значення.
Для цілих чисел PostgreSQL має кілька типів.
smallintsmallint займає 2 байти та зберігає числа приблизно від -32 768 до 32 767.
Такий тип підходить для невеликих значень, наприклад рейтингу від 1 до 5:
CREATE TABLE reviews (
rating smallint
);integerinteger, або скорочено int, займає 4 байти. Це найпоширеніший тип для цілих чисел.
CREATE TABLE products (
id integer,
quantity integer
);Діапазон integer — приблизно від -2,1 мільярда до 2,1 мільярда.
bigintbigint займає 8 байтів і призначений для дуже великих цілих чисел.
CREATE TABLE events (
id bigint,
views bigint
);Зазвичай для звичайних ідентифікаторів достатньо integer або спеціального типу bigserial. bigint варто використовувати, коли значення справді можуть бути дуже великими.
numeric і decimalnumeric та decimal є синонімами. Вони зберігають числа з точною десятковою точністю.
Цей тип підходить для:
цін;
сум грошей;
відсотків;
інших значень, де важлива точність.
CREATE TABLE orders (
total numeric(10, 2)
);У записі numeric(10, 2):
10 — максимальна загальна кількість цифр;
2 — кількість цифр після десяткової крапки.
Наприклад, стовпець може містити значення 1250.75.
Для грошових значень не варто використовувати типи з плаваючою крапкою, якщо потрібні точні фінансові обчислення.
real і double precisionЦі типи використовують для чисел із плаваючою крапкою:
real — одинарна точність;
double precision — подвійна точність.
Вони можуть зберігати дуже великі або дуже малі числа, але не всі десяткові значення зберігаються абсолютно точно.
CREATE TABLE measurements (
temperature real,
distance double precision
);Для приблизних вимірювань такі типи підходять. Для цін краще використовувати numeric.
texttext зберігає текст змінної довжини.
CREATE TABLE articles (
title text,
content text
);У PostgreSQL text може зберігати рядки великого розміру.
varcharvarchar також зберігає текст змінної довжини. За потреби можна вказати максимальну довжину:
CREATE TABLE users (
username varchar(50)
);Тепер значення в username не може містити більше ніж 50 символів.
Якщо обмеження довжини не потрібне, можна написати просто varchar, але text зазвичай є простішим і зрозумілішим вибором.
charchar(n) зберігає рядок фіксованої довжини.
CREATE TABLE countries (
code char(2)
);Такий тип може бути корисним для значень, які завжди мають однакову довжину, наприклад двосимвольних кодів. Для більшості звичайних текстових полів краще використовувати text або varchar.
PostgreSQL розрізняє великі та малі літери в текстових значеннях:
SELECT 'Admin' = 'admin';Результат буде false, оскільки рядки відрізняються.
booleanТип boolean зберігає логічне значення:
true;
false;
NULL, якщо значення не задане.
CREATE TABLE tasks (
title text,
is_completed boolean
);
INSERT INTO tasks (title, is_completed)
VALUES
('Вивчити SQL', false),
('Створити таблицю', true);Для перевірки логічного значення можна використовувати:
SELECT title
FROM tasks
WHERE is_completed = true;Або коротший варіант:
SELECT title
FROM tasks
WHERE is_completed;Для перевірки false можна написати:
SELECT title
FROM tasks
WHERE NOT is_completed;PostgreSQL має окремі типи для дат і часу.
datedate зберігає календарну дату без часу:
CREATE TABLE employees (
name text,
birth_date date
);
INSERT INTO employees (name, birth_date)
VALUES ('Олена', '1995-04-12');Значення дати зазвичай записують у форматі YYYY-MM-DD.
timetime зберігає час без дати:
CREATE TABLE working_hours (
opening_time time,
closing_time time
);timestamptimestamp зберігає дату й час без інформації про часовий пояс:
CREATE TABLE logs (
created_at timestamp
);timestamptztimestamptz — це скорочена назва timestamp with time zone. Тип призначений для моментів часу, які потрібно коректно обробляти з урахуванням часових поясів.
CREATE TABLE messages (
sent_at timestamptz
);Для часу створення запису часто використовують значення за замовчуванням:
CREATE TABLE posts (
title text,
created_at timestamptz DEFAULT now()
);Якщо created_at не вказати під час вставки, PostgreSQL автоматично використає поточні дату й час.
uuidДля ідентифікаторів часто використовують цілі числа:
CREATE TABLE categories (
id integer,
name text
);Також можна використовувати uuid — універсальний унікальний ідентифікатор. Він має формат на кшталт:
550e8400-e29b-41d4-a716-446655440000Приклад таблиці з uuid:
CREATE TABLE accounts (
id uuid,
email text
);UUID зручні, коли ідентифікатори мають бути унікальними не лише в одній таблиці або базі даних.
jsonbjsonb зберігає дані у форматі JSON у бінарному представленні PostgreSQL. Він підходить для структурованих даних, структура яких може відрізнятися.
CREATE TABLE products (
id integer,
name text,
attributes jsonb
);
INSERT INTO products (id, name, attributes)
VALUES (
1,
'Ноутбук',
'{"color": "silver", "memory_gb": 16}'
);Отримати значення з JSON можна за допомогою операторів PostgreSQL:
SELECT attributes ->> 'color' AS color
FROM products;Оператор ->> повертає значення JSON як текст.
jsonb не варто використовувати для всіх даних підряд. Якщо структура даних стабільна, зазвичай краще створити окремі стовпці з відповідними типами.
PostgreSQL підтримує масиви значень. Тип масиву позначають квадратними дужками після базового типу.
CREATE TABLE articles (
title text,
tags text[]
);
INSERT INTO articles (title, tags)
VALUES (
'Основи SQL',
ARRAY['sql', 'postgresql', 'database']
);Перевірити, чи містить масив певне значення, можна за допомогою оператора @>:
SELECT title
FROM articles
WHERE tags @> ARRAY['postgresql'];Масиви зручні для простих списків, але для складних зв’язків між сутностями зазвичай створюють окремі таблиці.
NULLNULL означає відсутність значення. Це не те саме, що:
порожній рядок '';
число 0;
false.
Наприклад, у таблиці:
CREATE TABLE profiles (
name text,
phone text
);можна створити запис без номера телефону:
INSERT INTO profiles (name)
VALUES ('Андрій');У такому разі phone матиме значення NULL.
Для перевірки NULL використовують IS NULL та IS NOT NULL:
SELECT name
FROM profiles
WHERE phone IS NULL;Порівняння через = для NULL не працює очікуваним чином:
-- Неправильна перевірка
SELECT name
FROM profiles
WHERE phone = NULL;Правильний варіант:
SELECT name
FROM profiles
WHERE phone IS NULL;Нижче наведено повний приклад, який можна виконати в PostgreSQL:
DROP TABLE IF EXISTS products;
CREATE TABLE products (
id integer,
name text NOT NULL,
price numeric(10, 2) NOT NULL,
quantity integer DEFAULT 0,
is_available boolean DEFAULT true,
published_on date,
created_at timestamptz DEFAULT now(),
metadata jsonb
);
INSERT INTO products (
id,
name,
price,
quantity,
is_available,
published_on,
metadata
)
VALUES
(
1,
'Клавіатура',
1499.90,
12,
true,
'2026-03-01',
'{"color": "black", "layout": "US"}'
),
(
2,
'Миша',
799.50,
0,
false,
NULL,
'{"color": "white", "wireless": true}'
);
SELECT
id,
name,
price,
quantity,
is_available,
published_on,
created_at,
metadata
FROM products;У цьому прикладі:
id має тип integer;
name — text;
price — точне десяткове число;
quantity — ціле число;
is_available — логічне значення;
published_on — дата;
created_at — дата й час із часовим поясом;
metadata — JSON-дані;
NULL у published_on означає, що товар ще не опублікований.
Під час проєктування таблиці поставте собі такі запитання:
Значення є цілим числом чи може містити дробову частину?
Чи потрібна точність для десяткових значень?
Яка максимальна довжина тексту?
Це дата, час або момент часу з часовим поясом?
Чи може значення бути відсутнім?
Дані мають стабільну структуру чи краще зберігати їх як JSON?
Чи потрібен масив, чи краще окрема таблиця?
Практичні базові рекомендації:
для звичайних цілих чисел використовуйте integer;
для дуже великих цілих чисел — bigint;
для цін — numeric;
для звичайного тексту — text;
для прапорців і станів — boolean;
для календарних дат — date;
для моментів часу — timestamptz;
для змінних структур — jsonb, але лише коли це справді виправдано.
float для грошейЧисла з плаваючою крапкою можуть мати похибки під час обчислень.
-- Для грошових значень краще так
price numeric(10, 2)NULL через =-- Неправильно
WHERE value = NULL
-- Правильно
WHERE value IS NULLЯкщо зберігати дату, число або логічне значення як text, PostgreSQL не зможе повноцінно перевіряти та обробляти ці дані як відповідний тип.
Наприклад, ціну краще зберігати як numeric, а не як текст '1499.90'.
varchar(n)Обмеження довжини потрібне, якщо воно є частиною правил предметної області. В інших випадках text є достатнім типом для тексту.
timestamp і timestamptzЯкщо значення описує конкретний момент часу, наприклад час створення замовлення, зазвичай доречніше використовувати timestamptz.
Тип даних визначає, які значення може зберігати стовпець.
Для цілих чисел використовують smallint, integer і bigint.
Для точних десяткових значень, зокрема грошей, використовують numeric або decimal.
Для приблизних дробових обчислень існують real і double precision.
Текст можна зберігати в text, varchar або char.
Логічні значення мають тип boolean.
Для дат і часу використовують date, time, timestamp та timestamptz.
uuid призначений для універсальних унікальних ідентифікаторів.
jsonb зберігає структуровані JSON-дані.
NULL означає відсутність значення та перевіряється через IS NULL або IS NOT NULL.
Тип потрібно вибирати відповідно до змісту даних, а не зберігати всі значення як текст.