8.1. Числовые типы#

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

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

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

Таблица 8.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

Синтаксис констант для числовых типов описан в разделе Раздел 4.1.2. Числовые типы имеют полный набор соответствующих арифметических операторов и функций. Дополнительную информацию см. в разделе Глава 9. Следующие разделы подробно описывают типы.

8.1.1. Типы целых чисел

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

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

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

8.1.2. Произвольная точность чисел

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

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

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

NUMERIC(precision, scale)

Точность должна быть положительной, в то время как масштаб может быть положительным или отрицательным (см. ниже). Вариант:

NUMERIC(precision)

выбирает масштаб 0. Указание:

NUMERIC

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

Примечание

Максимальная точность, которую можно явно указать в объявлении типа numeric, составляет 1000. Неограниченный столбец numeric подчиняется ограничениям, описанным в Таблица 8.2.

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

NUMERIC(3, 1)

округлит значения до 1 десятичного знака и может хранить значения в диапазоне от -99.9 до 99.9 включительно.

Начиная с Tantor SE-1C 15, разрешено объявлять столбец типа numeric с отрицательной шкалой. Тогда значения будут округляться влево от десятичной точки. Точность по-прежнему представляет максимальное количество нераспределенных цифр. Таким образом, столбец, объявленный как

NUMERIC(2, -3)

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

NUMERIC(3, 5)

будет округлять значения до 5 десятичных знаков и может хранить значения в диапазоне от -0.00999 до 0.00999 включительно.

Примечание

Tantor SE-1C позволяет задавать масштаб в объявлении типа numeric с любым значением в диапазоне от -1000 до 1000. Однако стандарт SQL требует, чтобы масштаб находился в диапазоне от 0 до precision. Использование масштабов за пределами этого диапазона, возможно, нельзя будет перенести на другие системы баз данных.

Числовые значения хранятся физически без дополнительных ведущих или завершающих нулей. Таким образом, заявленная точность и масштаб столбца являются максимумами, а не фиксированными выделениями. (В этом смысле тип 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 (не число), потому что это не имеет четкого определения. Обратите внимание, что бесконечность может быть сохранена только в неограниченном столбце numeric, так как она фактически превышает любое конечное ограничение точности.

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

Примечание

В большинстве реализаций концепция "не число" (not-a-number) не считается равной любому другому числовому значению (включая NaN). Чтобы позволить сортировку и использование значений типа numeric в древовидных индексах, Tantor SE-1C рассматривает значения 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)

8.1.3. Типы с плавающей точкой

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

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

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

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

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

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

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

Примечание

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

Для обеспечения совместимости с выводом, созданным более старыми версиями PostgreSQL, а также для возможности уменьшения точности вывода, параметр 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.

Примечание

IEEE 754 определяет, что NaN не должно сравниваться равным никакому другому значению с плавающей запятой (включая NaN). Чтобы позволить сортировку значений с плавающей запятой и использование в индексах на основе деревьев, Tantor SE-1C обрабатывает значения NaN как равные и большие, чем все значения, не являющиеся NaN.

Tantor SE-1C также поддерживает стандартные обозначения SQL для нечетких числовых типов: float и float(p). Здесь p указывает минимально допустимую точность в двоичных разрядах. Tantor SE-1C принимает значения от float(1) до float(24) как тип real, а значения от float(25) до float(53) выбирают тип double precision. Значения p вне допустимого диапазона вызывают ошибку. Если точность не указана для float, то это означает double precision.

8.1.4. Типы серий

Примечание

Этот раздел описывает специфический для PostgreSQL способ создания автоинкрементного столбца. Другой способ - использовать стандарт SQL-столбец идентификатора, описанный в CREATE TABLE.

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

CREATE TABLE tablename (
    colname SERIAL
);

эквивалентно указанию:

CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

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

Примечание

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

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

Имена типов serial и serial4 эквивалентны: оба создают столбцы типа integer. Имена типов bigserial и serial8 работают таким же образом, за исключением того, что они создают столбец типа bigint. bigserial следует использовать, если вы предполагаете использование более чем 231 идентификаторов за период жизни таблицы. Имена типов smallserial и serial2 также работают одинаково, за исключением того, что они создают столбец типа smallint.

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