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

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

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

Table 8-2. Числовые типы

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

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

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

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

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

Только в некоторых операционных системах тип bigint может функционировать неправильно, так как он зависит от поддержки компилятором восьмибайтовых целых чисел. На машинах, где такой поддержки нет, bigint работает также как integer, но по прежнему использует восемь байт для хранения. (Мы не беспокоимся, что это будет происзодить на каких-либо современных платформах.)

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

8.1.2. Числа с заданной точностью

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

Далее используются следующие термины: масштаб(scale) типа numeric — это количество десятичных разрядов в дробной части, справа от десятичной точки. Точность (precision) типа numeric — это общее количество значимых разрядов во всём числе, т.е. количество разрядов по обе стороны от десятичной точки. Таким образом, число 23.5141 имеет точность 6 и масштаб 4. Целые числа могут быть представлены с использованием масштаба ноль.

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

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

Точность должна быть положительным значением, масштаб должен быть либо положительным значением либо нулём. Можно также использовать и такой синтаксис:

NUMERIC(точность)

который обусловливает значение масштаба 0. Если задать:

NUMERIC

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

Note: Максимально разрешённая точность, которая явно задаётся при объявлении данного типа - это 1000; NUMERIC без указания точности говорит об ограничениях, описанных в Table 8-2.

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

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

В дополнение к обычным числовым значениям, тип numeric позволяет хранить специальное значение NaN, которое означает "not-a-number (не число)". Любые операции над NaN в качестве результата дают другое значение NaN. Когда это значение пищется как константа в команде SQL, вы должны заключить его в одинарные кавычки, например UPDATE table SET x = 'NaN'. При вводе, строка NaN разпознаётся независимо от регистра букв.

Note: В большинстве реализаций концепции "не число", NaN не считается равным какому либо числовому значению (включая NaN). Чтобы разрешить сортировку значениям numeric и использовать индексы, основанные на деревьях, PostgreSQL считает значения NaN равными или больше, чем все не-NaN значения.

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

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

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

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

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

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

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

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

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

Infinity
-Infinity
NaN

Это соответствует специальным значениям стандарта IEEE 754 для "бесконечности", "минус бесконечности" и значению "не-число" соответственно. (На машине, где арифметика с плавающей точкой не соответствует стандарту IEEE 754, эти значения, предположительно, не будут работать так, как ожидается). При записи этих значений как констант в командах SQL, вы должны заключить их в одинарные кавычки, например, UPDATE table SET x = 'Infinity'. При вводе этих строк, они распознаются независимо от регистра букв.

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

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

Note: До версии PostgreSQL 7.4, точность у float(p) означала количество десятичных разрядов. Для соответствия стандарту SQL, который говорит, что точность измеряется в двоичных разрядах — это было исправлено. Для типов real и double precision в мантиссе соответственно содержится 24 и 53 бит, что соответствует стандарту IEEE на реализацию чисел с плавающей точкой. На платформах не соответствующих стандарту IEEE, количество бит может быть меньше, но для простоты, на всех платформах используется одни и те же диапазоны p.

8.1.4. Серийные типы

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

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

эквивалента конструкции:

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

Таким образом, мы создали колонку с типом integer и назначили для неё значения по умолчанию, которые получаются с помощью генератора последовательности. Ограничение NOT NULL предназначено для того, чтобы иметь уверенность в том, что в колонку не могут быть вставлены значения null. (В большинстве случаев вам также понадобится применить ограничения UNIQUE или PRIMARY KEY, чтобы предотвратить появление в колонке дублированных значений. Эти ограничения не устанавливаются автоматически.) И наконец, последовательность отмечается как "принадлежащая" данной колонке, так что она будет удалена, если будет удалена эта колонка таблицы.

Note: До версии PostgreSQL 7.3, тип serial неявно включал ограничение UNIQUE. Но больше этого нет. Если вы хотите ограничение уникальности или первичного ключа для колонки с типом serial, вы теперь должны сделать его вручную, точно также как и для других типов данных.

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

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

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

Back to top

(С) Виктор Вислобоков, 2008-2023