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

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

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

ИмяРазмер храненияОписаниеДиапазон
smallint2 байтацелые числа малого диапазонаот -32768 до +32767
integer4 байтаобычные целые числаот -2147483648 до +2147483647
bigint8 байтцелые числа большого диапазонаот -9223372036854775808 до 9223372036854775807
decimalпеременныйчисла с точностью, указываемой пользователем, точное числобез ограничений
numericпеременныйчисла с точностью, указываемой пользователем, точное числобез ограничений
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 может хранить числа с точностью до 1000 знаков после точки и с этим типом могут выполняться точные вычисления. Использование этого типа собенно рекомендуется для хранения денежных значений и других величин, для которых требуется точность. Однако, для типа numeric, работа с арифметическими значениями осуществляется очень медленно по сравнению с целочисленными типами или типами с плавающей точкой, о которых рассказывается в следущем разделе.

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

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

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

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

NUMERIC(точность)

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

NUMERIC

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

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

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

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

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

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

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

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

На большистве платформ, тип 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'. При вводе этих строк, они распознаются независимо от регистра букв.

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 имя_таблицы (
    имя_колонки integer DEFAULT nextval('имя_таблицы_имя_колонки_seq') NOT NULL
);

Таким образом, мы создали колонку с типом 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 автоматически удаляется, когда удаляется колонка для которой генерируется эта последовательности и не удаляется в других случаях. (Это не так в версиях PostgreSQL до 7.3. Заметим, что это автоматическое удаление не будет работать для последовательности, созданной загруженным дампом от базы данных версий до 7.3; такой файл дампа не содержит информацию, которая необходима для создания соответствующей зависимой связи.) Таким образом, зависимость между последовательностью и колонкой может быть создана только для самой колонки serial. Если любые другие колонки ссылаются на эту же последовательность (предположим с помощью вызова функции nextval вручную), то они будут сломаны, если эта последовательность будет удалена. Использование последовательности колонки serial в такой манере считается плохим тоном; если вы хотите задействовать несколько колонок от одного генератора последовательности, создайте эту последовательность как независимый объект.