Числовые типы

Числовые типы включают в себя двух-, четырех- и восьмибайтные целые числа, четырех- и восьмибайтные числа с плавающей запятой и десятичные числа с выбираемой точностью. В Таблице 2 перечислены имеющиеся типы.

Таблица 2. Числовые типы

ИмяРазмерОписаниеДиапазон
smallint2 байтацелое число малого диапазонаот -32768 до +32767
integer4 байтатипичный выбор для целого числаот -2147483648 до +2147483647
bigint8 байтбольшое целое числоот -9223372036854775808 до +9223372036854775807
decimalпеременнаяуказанная пользователем точность, точнаядо 131072 цифр перед десятичной запятой и до 16383 цифр — после
numericпеременнаяуказанная пользователем точность, точнаядо 131072 цифр перед десятичной запятой и до 16383 цифр — после
real4 байтапеременная точность, приближеннаяточность в пределах 6 десятичных цифр
double precision8 байтпеременная точность, приближеннаяточность в пределах 15 десятичных цифр
smallserial2 байтанебольшое целое число с автоприращениемот 1 до 32767
serial4 байтацелое число с автоприращениемот 1 до 2147483647
bigserial8 байтбольшое целое число с автоприращениемот 1 до 9223372036854775807

Синтаксис констант для числовых типов описан в подразделе Константы. Числовые типы имеют полный набор соответствующих арифметических операторов и функций. Дополнительную информацию см. в главе Функции и операторы. Подробнее эти типы описаны в следующих разделах.


Целочисленные типы

Типы smallint, integer и bigint хранят целые числа, то есть числа без дробной части, имеющие различные диапазоны. Попытки сохранить значения, выходящие за пределы допустимого диапазона, приведут к ошибке.

Тип integer является наиболее распространенным, поскольку он обеспечивает наилучший баланс между диапазоном, размером хранилища и производительностью. Тип smallint обычно используется только при нехватке объема дискового пространства. Тип bigint предназначен для тех случаев, когда диапазона типа integer недостаточно.

В SQL определены только целочисленные типы integer (или int), smallint и bigint. Имена типов int2, int4 и int8 являются расширениями, которые также используются некоторыми другими СУБД SQL.


Числа произвольной точности

Тип numeric может хранить числа с очень большим количеством цифр. Он особенно рекомендуется для хранения денежных сумм и других количественных величин, где требуется точность. Расчеты со значениями numeric дают точные результаты, где это возможно, например: сложение, вычитание, умножение. Однако операции со значениями numeric выполняются гораздо медленнее по сравнению с целочисленными типами или с типами с плавающей запятой, описываемыми в следующем разделе.

Ниже мы используем следующие термины: Точность значения numeric — это общее количество значимых цифр во всем числе, то есть количество цифр по обеим сторонам десятичной запятой. Масштаб значения numeric — это количество десятичных цифр в дробной части, справа от десятичной запятой. Таким образом, число 23,5141 имеет точность 6 и масштаб 4. Целые числа можно рассматривать как имеющие нулевой масштаб.

Для столбца numeric можно настроить как максимальную точность, так и максимальный масштаб. Чтобы объявить столбец типа numeric, используйте синтаксис:

NUMERIC(точность, масштаб)

Точность должна быть положительной, а масштаб — положительным или равным нулю. Альтернативный вариант:

NUMERIC(точность)

устанавливает масштаб 0. Форма:

NUMERIC

без указания точности или масштаба создает столбец, в котором можно сохранять числовые значения любой точности и масштаба, вплоть до предела реализации по точности. Столбец такого типа не будет приводить входные значения к какому-либо конкретному масштабу, тогда как столбцы numeric с объявленным масштабом будут приводить входные значения к этому масштабу. (Стандарт SQL требует, чтобы масштаб по умолчанию был равен 0, что соответствует приведению к целочисленной точности, но мы считаем это не очень полезным. Если вас заботит переносимость, всегда указывайте точность и масштаб явно.)

Примечание
Максимально допустимая точность, если она явно указана в объявлении типа, составляет 1000; NUMERIC без указанной точности подпадает под ограничения, описанные в Таблице 2.

Если масштаб сохраняемого значения больше, чем объявленный масштаб столбца, система округляет значение до указанного числа дробных цифр. Затем, если число цифр слева от десятичной запятой превышает объявленную точность минус заявленная шкала, возникает ошибка.

Числовые значения физически хранятся без каких-либо дополнительных нулей в начале или конце. Таким образом, заявленная точность и масштаб столбца определяют максимальный, а не фиксированный выделенный размер. (В этом смысле тип numeric больше похож на varchar(n) чем на char(n).) Фактическое требование к размеру хранения составляет два байта для каждой группы из четырех десятичных разрядов плюс дополнительные три-восемь байт.

В дополнение к обычным числовым значениям у типа numeric имеется несколько специальных значений:

Infinity
-Infinity
NaN

Это адаптированные из стандарта IEEE 754 значения, которые представляют «бесконечность», «минус бесконечность» и «не число» соответственно. Записывая эти значения в виде констант в команде SQL, их следует заключать в апострофы, например так: UPDATE table SET x = '-Infinity'. Во входных значениях такие строки распознаются без учета регистра. Как вариант, значения бесконечности можно записать как inf и -inf.

Значения бесконечности ведут себя в соответствии с математическими ожиданиями. Например, Infinity плюс любое конечное значение равно Infinity, как и Infinity плюс Infinity; но Infinity минус Infinity дает NaN (not a number, не число), поскольку у него нет четко определенной интерпретации. Обратите внимание, что бесконечность можно сохранить только в столбце типа numeric, не имеющем ограничений, потому что семантически она превышает любой конечный предел точности.

Значение NaN (не число) используется для представления неопределенных результатов вычислений. В целом, любая операция с входным NaN выдает тот же NaN. Единственное исключение составляют операции, в которых другие входные значения таковы, что один и тот же результат можно получить, даже если заменить NaN любым конечным или бесконечным числовым значением; значит, это выходное значение будет использовано и для NaN. (Пример этого принципа: результатом возведения NaN в нулевую степень будет единица.)

Примечание
В большинстве реализаций концепции «не число» NaN не считается равным любому другому числовому значению (включая сам NaN). Чтобы разрешить сортировку и использование значений numeric в древовидных индексах, QHB рассматривает значения NaN как равные друг другу и превышающие все значения, отличные от NaN.

Типы decimal и numeric равнозначны. Оба эти типа включены в стандарт SQL.

При округлении значений тип numeric выдает число, большее по модулю, в то время как (на большинстве машин) типы real и double precision выдают ближайшее четное число. Например:

SELECT x,
  round(x::numeric) AS num_round,
  round(x::double precision) AS dbl_round
FROM generate_series(-3.5, 3.5, 1) as x;
  x   | num_round | dbl_round
------+-----------+-----------
 -3.5 |        -4 |        -4
 -2.5 |        -3 |        -2
 -1.5 |        -2 |        -2
 -0.5 |        -1 |        -0
  0.5 |         1 |         0
  1.5 |         2 |         2
  2.5 |         3 |         2
  3.5 |         4 |         4
(8 rows)

Типы с плавающей запятой

Типы данных real и double precision хранят приближенные числовые значения переменной точности. На всех поддерживаемых в настоящее время платформах эти типы являются реализациями стандарта IEEE 754 для двоичной арифметики с плавающей запятой (одинарной и двойной точности соответственно) в той степени, в которой это поддерживается базовым процессором, операционной системой и компилятором.

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

  • Если вам требуется точное хранение и расчеты (например, для денежных сумм), используйте вместо этого тип numeric.

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

  • Проверка равенства двух значений с плавающей запятой может не всегда давать ожидаемый результат.

На всех поддерживаемых в настоящее время платформах тип real имеет диапазон от 1E-37 до 1E+37 с точностью не менее 6 десятичных цифр. Тип double precision имеет диапазон от 1E-307 до 1E+308 с точностью не менее 15 цифр. Слишком большие или слишком маленькие значения вызовут ошибку. Если точность вводимого числа слишком высока, возможно округление. Числа, слишком близкие к нулю и непредставимые отличными от нуля, вызовут ошибку обнуления.

По умолчанию значения с плавающей запятой выводятся в текстовой форме в кратчайшем точном десятичном представлении; полученное десятичное значение ближе к истинному сохраненному двоичному значению, чем к любому другому значению, представляемому с той же двоичной точностью. (Однако выводимое значение в настоящее время никогда не находится точно посередине между двумя представимыми значениями, во избежание широко распространенной ошибки, когда функции ввода не соблюдают должным образом правило округления до ближайшего четного.) Это значение будет использовать не более 17 значащих десятичных цифр для типа float8 и не более 9 цифр для типа float4.

Примечание
Этот кратчайший точный формат вывода генерируется намного быстрее, чем исторически сложившийся формат округления.

В целях снижения точности выводимых чисел, когда это требуется, в параметре extra_float_digits можно выбрать округление десятичного числа. При значении 0 восстанавливается предыдущее округление числа по умолчанию до 6 (для float4) или 15 (для float8) значащих десятичных цифр. При отрицательных значениях количество значащих цифр уменьшается; например, при -2 выводимое число будет округлено до 4 или 13 цифр соответственно.

При любом значении extra_float_digits больше 0 выбирается кратчайший точный формат.

Примечание
Приложениям, которым были нужны точные значения, раньше приходилось задавать для параметра extra_float_digits значение 3, чтобы получить их. Для максимальной совместимости между версиями они должны продолжать это делать.

В дополнение к обычным числовым значениям типы с плавающей запятой имеют несколько специальных значений:

Infinity
-Infinity
NaN

Они представляют специальные значения IEEE 754 «бесконечность», «минус бесконечность» и «не число» соответственно. При записи этих значений в качестве констант в команде SQL необходимо заключить их в апострофы, например UPDATE table SET x = '-Infinity'. При вводе эти строки распознаются без учета регистра. Как вариант, значения бесконечности можно записать как inf и -inf.

Примечание
В IEEE754 указано, что NaN нельзя сравнивать с любым другим значением с плавающей запятой (включая сам NaN). Чтобы значения с плавающей запятой можно было сортировать и использовать в древовидных индексах, QHB рассматривает значения NaN как равные друг другу и превышающие все значения, отличные от NaN.

QHB также поддерживает стандартные обозначения SQL float и float(p) для указания неточных числовых типов. Здесь p задает минимально допустимую точность в двоичных цифрах. QHB принимает значения от float(1) до float(24) как выбор типа real, а значения от float(25) до float(53) — как выбор типа double precision. Значения p вне допустимого диапазона вызывают ошибку. float без заданной точности считается double precision.


Последовательные типы

Примечание
В этом разделе описывается специфичный для QHB способ создания столбца с автоприращением. Другой способ — использовать функцию столбца идентификаторов стандарта SQL, рассматриваемую в описании команды CREATE TABLE.

Типы данных smallserial, serial и bigserial представляют собой не настоящие типы, а просто удобное средство для создания столбцов с уникальными идентификаторами (аналогично свойству AUTO_INCREMENT, поддерживаемому некоторыми базами данных). В текущей реализации указание:

CREATE TABLE имя_таблицы (
    имя_столбца SERIAL
);

равнозначно указанию:

CREATE SEQUENCE имя_таблицы_имя_столбца_seq AS integer;
CREATE TABLE имя_таблицы (
    имя_столбца integer NOT NULL DEFAULT nextval('имя_таблицы_имя_столбца_seq')
);
ALTER SEQUENCE имя_таблицы_имя_столбца_seq OWNED BY имя_таблицы.имя_столбца;

Таким образом, создается целочисленный столбец, у которого значения по умолчанию назначаются из генератора последовательности. Чтобы в этот столбец нельзя было вставить значение NULL, применяется ограничение NOT NULL. (В большинстве случаев имеет смысл также добавить ограничение UNIQUE или PRIMARY KEY, чтобы предотвратить случайную вставку дублирующихся значений, но автоматически это не происходит.) Последняя команда помечает последовательность как «принадлежащую» столбцу, поэтому при удалении столбца или таблицы она также будет удалена.

Примечание
Поскольку типы smallserial, serial и bigserial реализованы с использованием последовательностей, в последовательности значений, находящейся в столбце, могут появляться «дыры» или пропуски, даже если не удалять никакие строки. Значение, выделенное из последовательности, все равно «израсходуется», даже если строку, содержащую это значение, так и не удастся успешно вставить в столбец таблицы. Это может произойти, например, при откате транзакции вставки. См. подробное описание nextval() в разделе Функции для управления последовательностями.

Чтобы вставить следующее значение последовательности в столбец serial, укажите, что этому столбцу следует присвоить его значение по умолчанию. Это можно сделать либо путем исключения столбца из списка столбцов в команде INSERT, либо с помощью ключевого слова DEFAULT.

Имена типов serial и serial4 равнозначны: оба создают столбцы integer. Имена типов bigserial и serial8 работают аналогично, за исключением того, что они создают столбец bigint. Тип bigserial следует использовать, если за время существования таблицы вы предполагаете использовать более 231

идентификаторов. Имена типов smallserial и serial2 также работают аналогично, за исключением того, что они создают столбец smallint.

Последовательность, созданная для столбца serial, автоматически удаляется при удалении столбца-владельца. Последовательность можно удалить, не удаляя столбец, но это приведет к удалению выражения по умолчанию для этого столбца.