Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы данных SQL: полный справочник
Типы данных — это основа структуры БД. Рассмотрю все основные типы, их особенности и когда их использовать.
Категория 1: Числовые типы
Целые числа (Integer)
TINYINT → -128 до 127 (1 байт) [MySQL]
SMALLINT → -32768 до 32767 (2 байта) [PostgreSQL, MySQL]
INTEGER / INT → -2^31 до 2^31-1 (4 байта) [Стандарт]
BIGINT → -2^63 до 2^63-1 (8 байт) [PostgreSQL, MySQL]
Примеры использования:
TINYINT: статус (0=активный, 1=удален)
SMALLINT: количество товара (0-1000)
INT: ID пользователя (обычно используют)
BIGINT: timestamp в миллисекундах, большие ID
Числа с плавающей точкой (Float/Decimal)
FLOAT → приблизительные (4 байта)
DOUBLE → приблизительные (8 байт)
DECIMAL(p, s) → точные (p = всего цифр, s = после запятой)
NUMERIC(p, s) → синоним DECIMAL
Примеры:
FLOAT(7, 2) → 99999.99 (7 цифр, 2 после запятой)
DECIMAL(10, 2) → 99999999.99
Правило: используйте DECIMAL для денег
-- ❌ ПЛОХО - потеря точности
CREATE TABLE orders (
price FLOAT
);
INSERT INTO orders VALUES (0.1);
INSERT INTO orders VALUES (0.2);
SELECT SUM(price) FROM orders;
-- Результат может быть 0.30000000000004 вместо 0.3
-- ✅ ХОРОШО - точные вычисления
CREATE TABLE orders (
price DECIMAL(10, 2)
);
INSERT INTO orders VALUES (0.10);
INSERT INTO orders VALUES (0.20);
SELECT SUM(price) FROM orders;
-- Результат: 0.30 (точно)
Категория 2: Строки (String)
Текстовые типы
CHAR(n) → фиксированная длина n байт
"Hello" в CHAR(10) = "Hello " (с пробелами)
Используйте для кодов: "US", "RU"
VARCHAR(n) → переменная длина до n байт
"Hello" в VARCHAR(10) = "Hello" (без лишних пробелов)
Используйте для имен, email, адресов
TEXT → очень длинный текст (до 4GB в MySQL)
CLOB → Character Large Object (PostgreSQL)
LONGTEXT → MySQL, до 4GB
Примеры использования:
Когда использовать CHAR vs VARCHAR
-- ✅ CHAR для фиксированной длины
CREATE TABLE countries (
code CHAR(2) -- "US", "FR", "RU"
);
-- ✅ VARCHAR для переменной длины
CREATE TABLE users (
email VARCHAR(255), -- разная длина
username VARCHAR(100),
full_name VARCHAR(255)
);
Сравнение размер
Данные: "Hello"
CHAR(20) : 5 + 15 пробелов = 20 байт (всегда)
VARCHAR(20): 1 байт (длина) + 5 байт (данные) = 6 байт
ВЫВОД: VARCHAR экономит место для текста переменной длины
Категория 3: Дата и время
Типы DateTime
DATE → 'YYYY-MM-DD' (3 байта)
TIME → 'HH:MM:SS' (3 байта)
DATETIME / TIMESTAMP → 'YYYY-MM-DD HH:MM:SS' (8 байт)
TIMESTAMP → 'YYYY-MM-DD HH:MM:SS' автоматически обновляется
TIMESTAMPZ → с указанием временной зоны (PostgreSQL)
Примеры:
Правило: всегда используйте TIMESTAMP с часовым поясом
-- ❌ НЕПРАВИЛЬНО - теряется информация о часовом поясе
CREATE TABLE events (
event_time DATETIME
);
-- Проблема: 2026-03-28 10:00:00 (какой часовой пояс?)
-- ✅ ПРАВИЛЬНО - сохраняется часовой пояс
CREATE TABLE events (
event_time TIMESTAMPTZ -- PostgreSQL
);
-- или
CREATE TABLE events (
event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- MySQL
timezone VARCHAR(50)
);
Работа с датами
-- Текущая дата
SELECT CURRENT_DATE; -- 2026-03-28
SELECT CURRENT_TIME; -- 15:30:45
SELECT CURRENT_TIMESTAMP; -- 2026-03-28 15:30:45
-- Операции с датами
SELECT CURRENT_DATE + INTERVAL '1 day'; -- 2026-03-29
SELECT CURRENT_TIMESTAMP - INTERVAL '1 week'; -- неделю назад
-- Разница между датами
SELECT AGE(CURRENT_TIMESTAMP, created_at) AS account_age
FROM users;
Результат: "1 year 3 months 5 days"
Категория 4: Булевы значения (Boolean)
BOOLEAN / BOOL → TRUE or FALSE (1 байт в PostgreSQL)
0 = FALSE, 1 = TRUE (в MySQL)
Примеры использования:
Использование boolean
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255),
is_active BOOLEAN DEFAULT TRUE, -- активный пользователь
is_admin BOOLEAN DEFAULT FALSE, -- администратор
email_verified BOOLEAN DEFAULT FALSE -- email подтвержден
);
-- Запросы
SELECT * FROM users WHERE is_active = TRUE;
SELECT * FROM users WHERE is_active; -- эквивалентно
SELECT * FROM users WHERE NOT is_admin;
Категория 5: JSON/JSONB
JSON → текстовое хранилище JSON (PostgreSQL, MySQL)
JSONB → бинарное хранилище JSON с индексами (PostgreSQL)
Преимущества:
✅ Гибкая структура данных
✅ Индексирование отдельных полей
✅ Встроенные функции для работы с JSON
Примеры
CREATE TABLE users (
id UUID PRIMARY KEY,
name VARCHAR(255),
metadata JSONB -- Хранить дополнительные данные
);
INSERT INTO users VALUES (
'user_123',
'John',
'{"phone": "+1234567890", "address": {"city": "NYC"}, "tags": ["vip", "premium"]}'
);
-- Доступ к JSON полям
SELECT
name,
metadata->>'phone' as phone, -- строка
metadata->'address'->>'city' as city, -- вложенный объект
metadata->'tags'->0 as first_tag -- массив
FROM users;
-- Поиск в JSON
SELECT * FROM users WHERE metadata @> '{"tags": ["vip"]}';
-- Создание индекса на JSON
CREATE INDEX idx_users_metadata_tags ON users USING GIN (metadata->'tags');
Категория 6: UUID
UUID → глобально уникальный идентификатор (16 байт)
Пример: 550e8400-e29b-41d4-a716-446655440000
Преимущества:
✅ Глобально уникален (работает в распределенных системах)
✅ Безопасен (невозможно угадать)
✅ Не раскрывает количество записей
✅ Может быть сгенерирован на клиенте
Использование UUID
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- PostgreSQL
email VARCHAR(255),
created_at TIMESTAMP
);
-- в MySQL используйте UUID() функцию
CREATE TABLE users (
id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
email VARCHAR(255)
);
Категория 7: ENUM
ENUM → один из предопределенных значений (PostgreSQL)
Пример:
Использование ENUM
-- Создание ENUM типа
CREATE TYPE order_status AS ENUM ('pending', 'processing', 'shipped', 'delivered', 'cancelled');
-- Использование в таблице
CREATE TABLE orders (
id UUID PRIMARY KEY,
status order_status DEFAULT 'pending',
created_at TIMESTAMP
);
-- Вставка данных
INSERT INTO orders (id, status) VALUES ('order_1', 'processing');
-- Преимущества ENUM:
✅ Ограничивает возможные значения
✅ Экономит место (2 байта вместо VARCHAR)
✅ Быстрее сравнение
-- Недостатки:
❌ Сложно добавить новое значение (нужна миграция)
❌ Не все БД поддерживают
Категория 8: Бинарные данные
BINARY(n) → фиксированная длина (n байт)
VARBINARY(n) → переменная длина до n байт
BLOB → Binary Large Object (до 4GB)
BYTEA → в PostgreSQL
Использование:
Когда использовать BLOB/BYTEA
-- ❌ ПЛОХО - хранить файлы в БД
CREATE TABLE documents (
id UUID PRIMARY KEY,
file BLOB -- 10MB файл
);
-- Проблема: медленный backup, замедляет запросы
-- ✅ ХОРОШО - хранить в S3, ссылку в БД
CREATE TABLE documents (
id UUID PRIMARY KEY,
s3_url VARCHAR(500), -- ссылка на S3
file_size INTEGER,
mime_type VARCHAR(50)
);
Специальные типы (PostgreSQL)
Array
CREATE TABLE user_tags (
user_id UUID,
tags TEXT[] -- массив текста
);
INSERT INTO user_tags VALUES ('user_1', ARRAY['vip', 'premium', 'beta']);
SELECT * FROM user_tags WHERE 'vip' = ANY(tags);
Range типы
CREATE TABLE availability (
id UUID PRIMARY KEY,
available_dates DATERANGE -- диапазон дат
);
INSERT INTO availability VALUES ('slot_1', '[2026-03-28, 2026-03-31)');
-- Проверка пересечения
SELECT * FROM availability
WHERE available_dates && DATERANGE('2026-03-29', '2026-04-01');
Сравнение типов для конкретных случаев
Для ID:
❌ INT - может переполниться
✅ BIGINT - безопаснее
✅ UUID - лучший выбор для распределенных систем
Для email:
❌ VARCHAR(1000) - слишком большая
✅ VARCHAR(255) - достаточно (RFC 5321 = 254 символа)
Для IP адреса:
❌ VARCHAR(15) - неправильная валидация
✅ INET (PostgreSQL) - встроенная валидация
✅ VARCHAR(45) - для IPv6
Для телефона:
❌ BIGINT - теряет лидирующие нули
✅ VARCHAR(20) - хранит как строка
Выбор правильного размера
Tип | Размер | Максимум | Использование
────────────────────┼─────────┼───────────────────┼──────────────
TINYINT | 1 байт | 255 | status
SMALLINT | 2 байта | 65535 | количество
INT | 4 байта | 2.1B | ID
BIGINT | 8 байт | 9.2 квинтиллион | timestamp
DECIMAL(10,2) | 4-8 | 99999999.99 | деньги
CHAR(2) | 2 байта | "US" | коды
VARCHAR(255) | 1-256 | 255 символов | строки
DATE | 3 байта | 2038 год | дата
TIMESTAMPTZ | 8 байт | | точный момент
UUID | 16 байт | | ID
JSON | варьирующ | | гибкие данные
BOOLEAN | 1 байт | TRUE/FALSE | флаги
Best Practices
1. Используйте правильные типы
✅ Деньги → DECIMAL(10,2)
✅ Дата/время → TIMESTAMP WITH TIMEZONE
✅ ID → UUID или BIGINT
✅ Флаги → BOOLEAN
2. Выбирайте минимальный размер
❌ VARCHAR(1000) для email (max 255)
✅ VARCHAR(255) для email
❌ INT для дня месяца (0-31)
✅ SMALLINT или TINYINT
3. Используйте CONSTRAINT для ограничения значений
CREATE TABLE products (
id UUID PRIMARY KEY,
quantity INT CHECK (quantity >= 0),
discount DECIMAL(5,2) CHECK (discount BETWEEN 0 AND 100),
status VARCHAR(20) CHECK (status IN ('active', 'inactive', 'archived'))
);
4. Всегда используйте TIMESTAMP WITH TIMEZONE
❌ created_at TIMESTAMP
✅ created_at TIMESTAMPTZ DEFAULT NOW()
5. Документируйте семантику типов
-- Комментарии помогают разработчикам
CREATE TABLE users (
id UUID PRIMARY KEY COMMENT "Global unique ID",
email VARCHAR(255) NOT NULL COMMENT "Email адрес, уникален",
age INT COMMENT "Возраст в годах, 0-150",
balance DECIMAL(10,2) COMMENT "Баланс в USD с 2 знаками"
);
Вывод
Основные категории типов SQL:
- Числовые: INT, BIGINT, DECIMAL
- Строки: VARCHAR, TEXT, CHAR
- Дата/время: DATE, TIMESTAMP, TIMESTAMPTZ
- Булевы: BOOLEAN
- JSON: JSON, JSONB (гибкие данные)
- UUID: глобально уникальные ID
- ENUM: ограниченный набор значений
- Бинарные: BLOB, BYTEA
Золотые правила:
- Используйте DECIMAL для денег
- Используйте UUID для ID в распределенных системах
- Используйте TIMESTAMPTZ для дат
- Выбирайте минимальный размер для экономии памяти
- Ограничивайте значения constraints