Открыть сервис

Тип данных DECIMAL

DECIMAL (также NUMERIC) — это тип данных, используемый в системах управления базами данных (СУБД) и языках программирования для хранения чисел с фиксированной точностью и масштабом. В отличие от чисел с плавающей запятой (например, FLOAT или DOUBLE), DECIMAL хранит значения точно, без ошибок округления, что делает его незаменимым для финансовых расчётов, бухгалтерского учёта и других задач, где требуется высокая точность десятичных дробей.

История и стандарты

Тип DECIMAL был стандартизирован в языке SQL (первая версия — SQL-86, затем SQL:1992, SQL:2003). Первоначально он был предложен как альтернатива типам REAL и DOUBLE PRECISION (с плавающей точкой), которые допускают погрешности при арифметических операциях. Стандарт SQL определяет два синонимичных ключевых слова: DECIMAL и NUMERIC. Формально, по стандарту, NUMERIC гарантирует точное соблюдение заданной точности, а DECIMAL допускает реализацию с точностью не ниже указанной, хотя на практике большинство СУБД трактуют их как взаимозаменяемые.

В других областях, например, в языке программирования COBOL (1960-е годы), десятичные числа с фиксированной точкой использовались под названием PIC 9(n)V9(m) (PICTURE). Впоследствии концепция была заимствована всеми крупными СУБД: Oracle Database (тип NUMBER), PostgreSQL (тип numeric), MySQL (типы DECIMAL и NUMERIC), Microsoft SQL Server (типы DECIMAL и NUMERIC), а также многими специализированными бухгалтерскими и финансовыми системами.

Синтаксис и параметры

Тип DECIMAL обычно объявляется в формате:

``sql DECIMAL(точность, масштаб) ``

Примеры объявлений:

Отличия от NUMERIC, FLOAT, DOUBLE

ТипХранениеТочностьПрименение
DECIMAL / NUMERICДвоично-десятичное кодирование (BCD) или десятичное представлениеФиксированная, точнаяФинансы, бухгалтерия, налоги
FLOAT / REALС плавающей точкой (IEEE 754)Приблизительная, с ошибками округленияНаучные расчёты, статистика, графика
DOUBLE PRECISIONС плавающей точкой двойной точностиПриблизительная, более высокая точностьАналогично FLOAT, но с большей точностью

Устройство и хранение

Точное хранение DECIMAL основано на двоично-десятичном кодировании (BCD) или специализированных десятичных форматах (например, decfloat). Каждая цифра от 0 до 9 кодируется отдельным 4-битным полубайтом (в BCD) или используется упакованное представление (по две цифры на байт). В современных СУБД (PostgreSQL, SQL Server) применяются алгоритмы сжатия, позволяющие хранить до 9–16 цифр в одном 64-битном блоке.

Типичные размеры памяти для хранения:

Точное внутреннее устройство варьируется между СУБД.

Применение

Финансовый учёт и бухгалтерия

Наиболее частое и важное применение DECIMAL — хранение сумм, курсов валют, налогов, процентных ставок, коэффициентов. В бухгалтерском учёте (например, в план счетов, оборотно-сальдовые ведомости) все денежные значения должны храниться с абсолютной точностью до копейки (масштаб 2 и более). Использование FLOAT или DOUBLE может привести к накоплению ошибок округления, что недопустимо для финансовой отчётности и законодательных требований (например, правила МСФО и РСБУ в РФ).

Научные и статистические данные

В случаях, когда требуется строгая повторяемость и сопоставимость результатов (например, при обработке измерений с фиксированным количеством десятичных знаков), DECIMAL предпочтительнее чисел с плавающей запятой. Особенно это актуально в демографии, социологии, метеорологии при публикации официальных данных (коэффициенты рождаемости, доли населения, проценты).

Административные и государственные информационные системы

В России DECIMAL активно используется в системах Федерального казначейства, бюджетного учёта, налоговых расчётах (например, суммы НДС, начисления пеней). Также он применяется в государственных реестрах (ЕГРЮЛ, ЕГРИП), где хранятся денежные показатели или индексы.

Интернет-торговля и электронные кошельки

Поскольку любые транзакции с реальными деньгами требуют точности до копейки (или его аналога), DECIMAL является стандартом для хранения балансов счетов, стоимости товаров, комиссий и скидок в платёжных системах, криптобиржах и банковских API.

Особенности и ограничения

Арифметические операции

Арифметика с DECIMAL выполняется в десятичной системе счисления, поэтому результат сложения или умножения двух DECIMAL-чисел теоретически должен быть точным. Однако точность результата может потребовать большей точности, чем задано; в этом случае СУБД либо округляет результат по определённым правилам (банковское округление, математическое округление), либо выводит ошибку переполнения.

Производительность

Операции с DECIMAL медленнее, чем с FLOAT или DOUBLE, из-за необходимости использования эмуляции десятичной арифметики (особенно на процессорах без аппаратной поддержки BCD). В высоконагруженных системах (аналитические запросы, OLAP) это может потребовать оптимизации: например, перевод DECIMAL в целые числа (храня сумму в копейках) для ускорения расчётов.

Ограничения по диапазону

Максимальное значение DECIMAL зависит от точности. При точности 38 максимальное значение приблизительно равно 10^38 – 1. Для финансовых расчётов это более чем достаточно, но для астрономических или физических величин может потребоваться NUMERIC с большей точностью (за пределами SQL-стандарта, в специализированных библиотеках).

Поддержка в основных СУБД

СУБДПоддерживаемый типМаксимальная точностьОсобенности
PostgreSQLNUMERIC / DECIMAL131072 (при использовании numeric с указанием точности свыше 1000)Стандартный тип; поддерживает масштаб 0–16383
MySQL / MariaDBDECIMAL / NUMERIC65По умолчанию DECIMAL(10,0)
Microsoft SQL ServerDECIMAL / NUMERIC38Эквивалентны по функциональности
Oracle DatabaseNUMBER38NUMBER(p,s) — общий тип для точных и целых чисел
SQLiteНет отдельного DECIMALИспользует REAL или INTEGER; точность не гарантируется

Примеры использования

Создание таблицы с денежным полем (PostgreSQL): ``sql CREATE TABLE orders ( id SERIAL PRIMARY KEY, amount DECIMAL(12,2) NOT NULL, tax_rate DECIMAL(5,4) NOT NULL ); ``

Вставка и вычисление (SQL Server): ``sql INSERT INTO orders (amount, tax_rate) VALUES (1500, 0.2000); SELECT amount * tax_rate AS tax FROM orders; ` Результат: 300.000000` (точное значение, без потерь).

Хранение валютного курса (MySQL): ``sql CREATE TABLE exchange_rates ( currency_code CHAR(3), rate DECIMAL(10,6) -- например, 1.250000 (6 знаков после запятой) ); ``

Критика и альтернативы

Основной недостаток DECIMAL — медленная арифметика по сравнению с целыми числами. В некоторых высоконагруженных системах применяют «копеечное хранение»: сумму умножают на 100 (или на 10000 для четырёхзначных дробей) и хранят как BIGINT или INTEGER. Это позволяет использовать быструю целочисленную арифметику и снижает накладные расходы, но требует дополнительного контроля при делении. Такой подход часто используется в бэкенде электронных кошельков (например, YooMoney, Сбербанк API).

Существуют также библиотеки для языков программирования, предоставляющие десятичные числа высокой точности (Java — BigDecimal, PythonDecimal из модуля decimal, C# — decimal). Они не зависят от СУБД и используются для обработки чисел на стороне приложения.

Интересные факты

Источники

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →