Масштабируемые типы с фиксированной точкой
Масштабируемые типы с фиксированной точкой
Типы с фиксированной точкой позволяют управлять числами, которые должны вычисляться с дробной частью, задающейся количеством цифр после десятичной точки, или масштабом. Обычно масштабируемые типы нужны для финансовых значений и других чисел, которые являются результатом подсчета или выполнения арифметических операций над целыми элементами и частями элементов.
Предсказуемость результатов умножения и деления чисел с фиксированной точкой позволяет выбрать их для хранения денежных значений. Тем не менее, поскольку типы с фиксированной точкой имеют ограниченные "рамки", в которых могут размещаться числа, они являются причиной появления исключений переполнения или потери значимости возле их верхней и нижней границы. В странах, где единицы валюты представляют небольшие значения, нужно быть внимательным при выборе ограничений чисел.
Например, следующий оператор использует ставку налога (DECIMAL(5,4)) и чистую прибыль (NUMERIC (18, 2)):
UPDATE ATABLE
SET INCOME_AFTER_TAX = NET_PROFIT - (NET_PROFIT * TAX_RATE) ;
Пусть ставка налога будет 0.3333.
Пусть чистая прибыль будет 1234567890123456.78.
Результат:
ISC ERROR CODE:335544779
Integer overflow. The result of an integer operation caused the most significant bit of the result to carry.
(Переполнение целого числа. Результат целочисленной операции привел к переносу большинства значащих битов)
Firebird предоставляет два типа данных чисел с фиксированной точкой или масштабируемых: NUMERIC и DECIMAL. Каждый масштабируемый тип объявляется как TYPE(p, s), где p определяет точность (количество значащих цифр), а s - масштаб (размещение десятичной точки - т. е. количество цифр справа от символа десятичной точки).
В соответствии со стандартом SQL-92 оба типа NUMERIC и DECIMAL ограничивают хранимое число объявленным масштабом. Различие между этими двумя типами заключается в способе, каким ограничивается точность. Точность должна быть такой, "как объявлено" для столбцов типа NUMERIC, в то время как столбцы DECIMAL могут получать числа, чья точность по меньшей мере равна тому, что было объявлено, больше границы реализации.
Типы NUMERIC и DECIMAL, как они реализованы в Firebird, являются идентичными, за исключение случая, когда точность меньше пяти. Оба типа действительно соответствуют стандарту типа DECIMAL, NUMERIC не соответствует SQL-92.
Внутренне Firebird хранит масштабированное число как типы SMALLINT(16 бит), INTEGER (32 бита) или BIGINT(64 бита) в соответствии с объявленным размером точности. Его объявленная точность[21] сохраняется вместе с объявленным масштабом в виде отрицательного множителя масштаба[22], представляющего степень числа 10. Когда к числу происходит обращение для вывода или для расчетов, оно получается произведением хранимого целого на 10 в степени "множитель масштаба" ( 10(^множитель масштаба^) )
Например, для столбца, объявленного как NUMERIC(4,3), Firebird сохраняет внутренне число в виде SMALLINT. Если вы вводите число 7.2345, Firebird без сообщений округляет самую правую цифру (4) и сохраняет 16-битовое целое 7235 и множитель масштаба -3. Это число будет найдено как 7.235 (7235 * 10(^-3^)).
Тип данных NUMERIC
Формат типа данных NUMERIC:
NUMERIC(p,s)
Например, NUMERIC (4,2) определяет число, состоящее не более чем из четырех цифр, включая две цифры справа от десятичной точки. Следовательно, числа 89.12 и 4.321 будут сохранены в столбце NUMERIC(4,2) как 89.12 и 4.32 соответственно. Во втором примере последняя цифра 10(^-3^) выходит за пределы масштаба и просто отбрасывается.
И все же возможно хранение в этом столбце числа с большей точностью, чем было объявлено. Максимально здесь может быть 327.67 - т. е. число с точностью 5. Поскольку база данных хранит фактическое число как SMALLINT, числа не начинают вызывать ошибки переполнения, пока внутренне хранимое число не станет больше 32,767 или меньше -32,768.