Типы данных в SQL: таблица для MySQL, PostgreSQL, SQL Server и SQLite

Разбираем типы данных SQL: числа и DECIMAL, CHAR, VARCHAR и TEXT, даты, BOOLEAN и JSON.

В шпаргалке названия типов для MySQL, PostgreSQL, SQL Server и SQLite, а в примерах видно, что база делает с лишними копейками, длинной строкой и 30 февраля.

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 3177 статей автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3831 экспертное мнение Подписаться на Телеграм-канал
Обложка: Типы данных в SQL: таблица для MySQL, PostgreSQL, SQL Server и SQLite

Тип данных в SQL говорит базе, что лежит в столбце: целое число, деньги с копейками, строка, дата или «да/нет». От типа зависят место на диске, допустимые значения и то, как база сравнивает и сортирует строки. Основных групп пять: числовые, строковые, дата и время, логический и специальные (JSON, двоичные данные).

Короткое правило на старте: идентификаторы храните в INT или BIGINT, деньги в DECIMAL, текст в VARCHAR или TEXT, даты в DATE и TIMESTAMP. Ниже разберём каждую группу на примерах для MySQL, PostgreSQL, SQL Server и SQLite, с запросами и их выводом. Если сам язык пока в новинку, начните с обзора что такое SQL и зачем его учить.

CheckroiCheckroiПодборка курсов по SQL422 курса • 40 школСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Что такое тип данных в SQL и где его указывают

Рой проектирует таблицу базы данных на ноутбуке

Тип задают один раз, когда создают таблицу командой CREATE TABLE. Это команда из группы DDL, про группы команд у нас есть отдельный разбор DDL, DML, DCL и TCL, а саму базу перед этим создают по инструкции «Как создать базу данных в SQL».

Вот таблица заказов в MySQL, в которой встречаются почти все популярные типы:

CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer VARCHAR(100) NOT NULL,
  amount DECIMAL(10,2) NOT NULL,
  is_paid BOOLEAN DEFAULT FALSE,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO orders (customer, amount, is_paid) VALUES ('Анна', 1499.90, TRUE);
SHOW COLUMNS FROM orders;
+------------+---------------+------+-----+-------------------+-------------------+
| Field      | Type          | Null | Key | Default           | Extra             |
+------------+---------------+------+-----+-------------------+-------------------+
| id         | int           | NO   | PRI | NULL              | auto_increment    |
| customer   | varchar(100)  | NO   |     | NULL              |                   |
| amount     | decimal(10,2) | NO   |     | NULL              |                   |
| is_paid    | tinyint(1)    | YES  |     | 0                 |                   |
| created_at | datetime      | YES  |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
+------------+---------------+------+-----+-------------------+-------------------+

Обратите внимание на строку is_paid. Мы написали BOOLEAN, а MySQL сохранил tinyint(1). Одно и то же название типа в разных СУБД может означать разное, поэтому дальше смотрим на каждую базу отдельно.

Шпаргалка: основные типы данных в MySQL, PostgreSQL, SQL Server и SQLite

Стандарт SQL описывает общие типы, но каждая СУБД добавляет свои имена и ограничения. Таблица собрана по официальной документации: MySQL 8.4, PostgreSQL 17, SQL Server и SQLite.

Что храним MySQL PostgreSQL SQL Server SQLite
Целое число INT integer (int4) int INTEGER
Большое целое BIGINT bigint bigint INTEGER
Точная дробь, деньги DECIMAL(p,s) numeric(p,s) decimal(p,s) точного типа нет
Приближённая дробь FLOAT, DOUBLE real, double precision real, float REAL
Строка с лимитом длины VARCHAR(n) varchar(n) varchar(n), nvarchar(n) TEXT, лимит не проверяется
Длинный текст TEXT, LONGTEXT text nvarchar(max) TEXT
Дата DATE date date строка или число по договорённости
Дата и время DATETIME, TIMESTAMP timestamp, timestamptz datetime2 строка или число по договорённости
Да или нет BOOLEAN = TINYINT(1) boolean bit INTEGER 0 и 1
Двоичные данные BLOB, VARBINARY bytea varbinary BLOB

Если вы работаете с PostgreSQL через графический клиент, типы удобно выбирать прямо в мастере создания таблицы, как в инструкции «Как создать таблицу в pgAdmin 4».

Канал основателя Checkroi Вани Буявца3 800 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

Числовые типы данных: INT, DECIMAL и FLOAT

Числовые типы делятся на три семейства: целые, точные дробные и приближённые дробные. Перепутать их дороже всего: ошибка вылезает не сразу, а через полгода, когда в отчёте не сойдутся копейки.

Целые числа: TINYINT, SMALLINT, INT, BIGINT

Целые типы отличаются только размером и диапазоном. Цифры ниже взяты из справки MySQL по целым типам, у PostgreSQL диапазоны smallint, integer и bigint такие же (документация PostgreSQL о числах), а TINYINT там нет.

Тип Байт Диапазон со знаком Для чего
TINYINT 1 от −128 до 127 флаги, оценки от 1 до 5 (в PostgreSQL такого типа нет)
SMALLINT 2 от −32 768 до 32 767 год, номер этажа, небольшие счётчики
INT 4 от −2 147 483 648 до 2 147 483 647 id в таблицах до пары миллиардов строк
BIGINT 8 от −9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 id событий, логов, платежей

Размер легко проверить в PostgreSQL функцией pg_column_size:

SELECT pg_column_size(1::smallint) AS smallint_b,
       pg_column_size(1::int)      AS int_b,
       pg_column_size(1::bigint)   AS bigint_b;

 smallint_b | int_b | bigint_b
------------+-------+----------
          2 |     4 |        8

Выйти за диапазон не получится: PostgreSQL на SELECT 2147483647::int + 1; отвечает ERROR: integer out of range, MySQL на вставку 2 147 483 648 в столбец INT выдаёт ERROR 1264: Out of range value.

DECIMAL и NUMERIC: точные числа для денег

DECIMAL(p,s) хранит число ровно в том виде, в каком вы его записали. Первое число p задаёт, сколько цифр всего, второе s говорит, сколько из них после запятой. В DECIMAL(10,2) помещается 10 цифр, две из них копейки, значит максимум 99 999 999,99. NUMERIC во всех трёх крупных СУБД работает так же, как DECIMAL.

Лишние знаки после запятой база округлит. Вставим 99,999 в столбец amount из таблицы выше и прочитаем результат запросом SELECT:

INSERT INTO orders (customer, amount) VALUES ('Борис', 99.999);
SELECT customer, amount FROM orders WHERE customer = 'Борис';

 customer | amount
----------+--------
 Борис    | 100.00

Так ведут себя и MySQL, и PostgreSQL. MySQL при этом оставляет заметку Note 1265: Data truncated for column 'amount', которую видно только командой SHOW WARNINGS. Целую часть база не обрезает: на 123 456 789,00 PostgreSQL отвечает numeric field overflow и поясняет, что значение должно быть меньше 10^8.

Пределы точности разные: в MySQL у DECIMAL до 65 цифр (раздел о DECIMAL в документации MySQL), в SQL Server до 38 (decimal и numeric в Transact-SQL), в PostgreSQL до 131 072 цифр до запятой.

FLOAT, REAL и DOUBLE: быстрые, но приближённые

Типы с плавающей точкой хранят число в двоичном виде, и часть десятичных дробей в него не укладывается. Сравните два сложения в MySQL: первое во FLOAT-арифметике, второе в DECIMAL.

SELECT 0.1e0 + 0.2e0 AS float_sum, 0.1 + 0.2 AS decimal_sum;

+---------------------+-------------+
| float_sum           | decimal_sum |
+---------------------+-------------+
| 0.30000000000000004 |         0.3 |
+---------------------+-------------+

PostgreSQL на 0.1::float8 + 0.2::float8 показывает те же 0.30000000000000004. Для координат, физических замеров и коэффициентов моделей это не страшно. Для денег, остатков на складе и всего, что потом складывают в отчёте, берите DECIMAL.

Такие расчёты удобно тренировать на задачах с проверкой ответа, их дают многие курсы по SQL из нашего каталога.

Строковые типы данных: CHAR, VARCHAR и TEXT

Строковых типов три основных, и разница между ними в том, как база обращается с длиной.

  • CHAR(n): строка фиксированной длины. Короткое значение база дополняет пробелами до n.
  • VARCHAR(n): строка переменной длины, но не длиннее n символов. В MySQL n бывает от 0 до 65 535 (страница о CHAR и VARCHAR в документации MySQL).
  • TEXT: длинный текст без явного лимита, например описания товаров, комментарии, статьи.

Хвостовые пробелы CHAR при чтении отбрасывает, а VARCHAR хранит как есть. Проверка в PostgreSQL:

SELECT 'ab '::char(5) || '|' AS c, 'ab '::varchar(5) || '|' AS v;

  c  |  v
-----+------
 ab| | ab |

В PostgreSQL CHAR не даёт выигрыша в скорости. Документация прямо пишет, что по быстродействию char, varchar и text «практически не отличаются», а character(n) обычно оказывается медленнее остальных (символьные типы PostgreSQL). В большинстве случаев документация советует брать text или varchar(n), а лимит ставить, когда он нужен по смыслу.

Что будет, если строка длиннее лимита

Здесь базы ведут себя по-разному, и это частый источник потерянных данных.

-- PostgreSQL
INSERT INTO orders (customer, amount) VALUES (repeat('я', 101), 10);
ERROR:  value too long for type character varying(100)

-- MySQL в строгом режиме (по умолчанию)
ERROR 1406 (22001): Data too long for column 'customer' at row 1

-- MySQL с отключённым строгим режимом: SET SESSION sql_mode = '';
Warning 1265: Data truncated for column 'customer' at row 1
SELECT CHAR_LENGTH(customer) ...  -- 100

Без строгого режима MySQL обрезает строку до лимита без ошибки и сохраняет её. Если на старом сервере в sql_mode пусто, проверьте самые длинные значения в таблице: хвосты адресов и названий могли пропасть давно.

Кириллица, байты и NVARCHAR

В VARCHAR(100) число в скобках означает символы, а не байты. Но место на диске считается в байтах, и русская буква в UTF-8 занимает два:

SELECT char_length('Привет') AS chars, octet_length('Привет') AS bytes;

 chars | bytes
-------+-------
     6 |    12

В MySQL то же самое показывают CHAR_LENGTH и LENGTH. В SQL Server для текста на любых языках традиционно берут NVARCHAR(n), где n от 1 до 4000 или max (nchar и nvarchar в Transact-SQL). Если вы работаете именно с этой СУБД, загляните в курсы по Microsoft SQL Server. Пустая строка и отсутствие значения тоже разные вещи, подробно об этом в статье «NULL в SQL».

Типы для даты и времени

Календарь, часы и карточки с форматами дат на столе

Дату можно сохранить и строкой, но тогда база не проверит 30 февраля и не посчитает разницу между двумя днями. Для дат есть свои типы:

  • DATE хранит только дату: день рождения, дату договора.
  • TIME хранит только время суток, например начало смены.
  • DATETIME и TIMESTAMP хранят дату вместе со временем: момент заказа, входа, платежа.

Несуществующую дату обе базы отклоняют: на '2026-02-30 10:00:00' MySQL отвечает ERROR 1292: Incorrect datetime value, а PostgreSQL date/time field value out of range.

Главная разница в диапазонах. У TIMESTAMP в MySQL верхняя граница 2038-01-19 03:14:07 UTC (документация MySQL о датах), и следующую секунду он уже не примет:

SET time_zone = '+00:00';
INSERT INTO t_ts VALUES ('2038-01-19 03:14:07');  -- ок
INSERT INTO t_ts VALUES ('2038-01-19 03:14:08');
ERROR 1292 (22007): Incorrect datetime value: '2038-01-19 03:14:08' for column 'ts'

Для сроков кредитов, гарантий и подписок, которые уходят за 2038 год, в MySQL берите DATETIME. В PostgreSQL timestamp покрывает годы от 4713 до н. э. до 294276 н. э. (типы даты и времени PostgreSQL), а в SQL Server datetime2 работает с датами от 0001-01-01 до 9999-12-31 (datetime2 в Transact-SQL).

Логический тип и другие специальные типы

BOOLEAN: где он настоящий, а где нет

В PostgreSQL есть отдельный тип boolean со значениями true, false и NULL. Он понимает и строковые варианты (логический тип PostgreSQL):

SELECT 'yes'::boolean AS a, 'off'::boolean AS b, '1'::boolean AS c;

 a | b | c
---+---+---
 t | f | t

В MySQL BOOLEAN служит синонимом TINYINT(1): ноль считается ложью, любое другое число истиной (описание числовых типов MySQL). Отсюда ловушка: в столбец можно записать 5, и такое значение не равно TRUE.

CREATE TABLE t_b (b BOOLEAN);
INSERT INTO t_b VALUES (5);
SELECT b, b = TRUE AS eq_true, b IS TRUE AS is_true FROM t_b;

+------+---------+---------+
| b    | eq_true | is_true |
+------+---------+---------+
|    5 |       0 |       1 |
+------+---------+---------+

В SQL Server логические значения хранят в bit, где TRUE превращается в 1, а FALSE в 0 (тип bit в Transact-SQL). У SQLite отдельного логического типа нет, там те же 0 и 1. Ветвить запрос по такому флагу удобно через оператор CASE.

JSON и двоичные данные

Для данных без жёсткой структуры в MySQL есть тип JSON, в PostgreSQL есть json и jsonb. Второй хранит документ в разобранном двоичном виде: записывать его чуть дольше, а обрабатывать заметно быстрее (типы JSON в PostgreSQL):

SELECT '{"city": "Казань", "tags": ["sql", "json"]}'::jsonb ->> 'city' AS city;

  city
--------
 Казань

Картинки, PDF и другие файлы в базе хранят в двоичных типах: BLOB в MySQL и SQLite, bytea в PostgreSQL, varbinary в SQL Server. На практике чаще кладут файл в хранилище, а в базе хранят только путь к нему в VARCHAR.

Ваня БуявецКанал основателя Checkroi Вани БуявцаЗабирайте промпты и обучение по нейросетям в моём Телеграм-каналеБольше 3 800 человек уже применяют Claude Code, ChatGPT и другие нейросети в работе, учёбе, бизнесе и жизниПерейти в канал

Как преобразовать тип данных: CAST и неявные приведения

Явно поменять тип значения можно функцией CAST, она есть во всех четырёх СУБД:

SELECT CAST('2026-11-04' AS DATE) AS d, CAST('42' AS SIGNED) + 1 AS n;   -- MySQL
SELECT CAST('2026-11-04' AS DATE) AS d, '42'::int + 1 AS n;              -- PostgreSQL

-- результат в обеих базах

     d      | n
------------+----
 2026-11-04 | 43

Неявные приведения базы делают по-разному. MySQL на SELECT '5' + 3; спокойно отвечает 8. PostgreSQL тоже вернёт 8, пока '5' остаётся литералом, но на значение типа text откажется считать:

SELECT '5'::text + 3;
ERROR:  operator does not exist: text + integer

SELECT '5'::text::int + 3 AS n;   -- 8

Подменить пустое значение на число по умолчанию помогает функция COALESCE, но типы её аргументов тоже должны совпадать.

Динамическая типизация в SQLite

SQLite устроен иначе. Документация так и пишет: тип там связан с самим значением, а не со столбцом (типы данных в SQLite). Поэтому обычная таблица принимает почти что угодно:

CREATE TABLE t (n INTEGER, s VARCHAR(3));
INSERT INTO t VALUES ('сорок два', 'слишком длинная строка');
SELECT n, typeof(n), s, length(s) FROM t;

сорок два|text|слишком длинная строка|22

Начиная с версии 3.37.0 у SQLite есть таблицы STRICT, где тип проверяется (STRICT-таблицы SQLite). В них разрешены только базовые имена типов, и VARCHAR(3) уже не пройдёт, а строка в столбец INTEGER вызовет cannot store TEXT value in INTEGER column.

Как выбрать тип данных под столбец

Рой радуется аккуратно разложенным по ящикам данным

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

Столбец Тип Почему
id пользователя или заказа BIGINT запас по росту, переделывать INT на живой таблице больно
цена, сумма, баланс DECIMAL(12,2) копейки не теряются при сложении
количество на складе INT целое, сравнивается и суммируется
email, имя, город VARCHAR(255) или text длина переменная, лимит защищает от мусора
телефон, ИНН, индекс VARCHAR нужны ведущие нули и знак «+», считать не нужно
описание, отзыв TEXT длина непредсказуема
дата рождения DATE время суток не нужно
момент события TIMESTAMP или DATETIME сортировка и интервалы по времени
оплачен ли заказ BOOLEAN или bit два состояния плюс «неизвестно»
настройки, ответ внешнего API JSON или jsonb структура меняется от записи к записи

Частые ошибки с типами данных

  1. Деньги во FLOAT. Симптом: итог в отчёте расходится с суммой строк на копейку. Причина: двоичная дробь, как в примере с 0,1 + 0,2. Решение: DECIMAL(12,2) и пересчёт старых значений через CAST.
  2. Числа в строковом столбце. Симптом: сортировка ставит 10 перед 2. Причина: строки сравниваются посимвольно, и ORDER BY по ('9'), ('10'), ('2') выдаёт 10, 2, 9, а по тем же числам 2, 9, 10. Решение: числовой тип или CAST в сортировке. Как работает ORDER BY, мы разбирали в статье о сортировке по двум столбцам.
  3. Коды и телефоны в INT. Симптом: код 007 превратился в 7. Причина: у числа нет ведущих нулей, SELECT '007'::int возвращает 7. Решение: VARCHAR.
  4. INT для id быстрой таблицы. Симптом: вставка падает с ошибкой выхода за диапазон после 2 147 483 647 строк. Решение: BIGINT с первого дня для логов и событий.
  5. Проверка флага через = TRUE в MySQL. Симптом: часть строк не попадает в выборку. Причина: в TINYINT(1) лежит не только 1. Решение: IS TRUE или условие <> 0.

Где освоить SQL системно

С типами данных вы разобрались, дальше идут запросы с JOIN, индексы, транзакции и проектирование схемы. Разобраться со всем этим по порядку и с практикой быстрее на курсе. Ниже программы по SQL с ценой, длительностью и форматом, а путь до первой работы расписан в плане «Как стать SQL-разработчиком».

КурсШколаСтоимость со скидкойВ рассрочкуДлитель­ностьОбзор курса от Checkroi
Нейросети для рабочих задач
Перейти на сайт курса
SkillboxSkillbox31 290 ₽ - 1 месяцОбзор курса
SQL для анализа данных
Перейти на сайт курса
SkillboxSkillbox50 865 ₽6203 ₽/мес.2 месяцаОбзор курса
SQL-разработчик: тариф PRO
Перейти на сайт курса
Академия ЭдюсонЭдюсон89 900 ₽7491 ₽/мес.2 месяцаОбзор курса
SQL-разработчик: тариф Базовый
Перейти на сайт курса
Академия ЭдюсонЭдюсон79 900 ₽3329 ₽/мес.3 месяцаОбзор курса
Data-Driven подход в разработке продукта: SQL и Yandex DataLens
Перейти на сайт курса
ProductStarProductStar29 990 ₽2999 ₽/мес.1 месяцОбзор курса

Больше программ — в полном каталоге курсов по SQL

Часто задаваемые вопросы

Какие типы данных есть в SQL?

Основных групп пять: числовые (INT, BIGINT, DECIMAL, FLOAT), строковые (CHAR, VARCHAR, TEXT), дата и время (DATE, TIME, TIMESTAMP), логический BOOLEAN и специальные, например JSON и двоичные BLOB или bytea. Точные названия и пределы зависят от СУБД, сводная таблица для MySQL, PostgreSQL, SQL Server и SQLite есть в статье.

Чем DECIMAL отличается от FLOAT?

DECIMAL хранит число точно, с заданным количеством знаков после запятой, поэтому его берут для денег. FLOAT и DOUBLE хранят приближённое двоичное значение: в MySQL и PostgreSQL 0,1 + 0,2 в такой арифметике даёт 0,30000000000000004.

Что значит DECIMAL(10,2)?

Число из 10 цифр, две из которых стоят после запятой. Максимум в таком столбце 99 999 999,99. Лишние знаки после запятой база округлит, а слишком большую целую часть отклонит с ошибкой.

Чем VARCHAR отличается от TEXT?

VARCHAR(n) ограничивает длину строки n символами, TEXT нужен для длинного текста без явного лимита. В PostgreSQL по скорости varchar и text практически не отличаются, поэтому лимит ставят только там, где он нужен по смыслу.

Какой тип данных выбрать для даты?

Для даты без времени берите DATE, для момента события TIMESTAMP или DATETIME. В MySQL у TIMESTAMP верхняя граница 2038-01-19 03:14:07 UTC, поэтому сроки, которые уходят дальше, хранят в DATETIME.

Есть ли в MySQL тип BOOLEAN?

Писать BOOLEAN можно, но MySQL создаёт столбец TINYINT(1): ноль считается ложью, любое другое число истиной. Если в столбце окажется 5, условие = TRUE его не найдёт, а IS TRUE найдёт.

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!