Подтвердить что ты не робот

Почему целое число без знака недоступно в PostgreSQL?

Я столкнулся с этим сообщением (В чем разница между tinyint, smallint, mediumint, bigint и int в MySQL?) и понял, что PostgreSQL не поддерживает целое число без знака.

Может кто-нибудь помочь объяснить, почему это так?

В большинстве случаев я использую unsigned integer как автоматически увеличивающийся первичный ключ в MySQL. В таком дизайне, как я могу это преодолеть, когда я переношу свою базу данных с MySQL на PostgreSQL?

Спасибо.

4b9b3361

Ответ 1

Уже ответили, почему postgresql не имеет неподписанных типов. Однако я бы предложил использовать домены для неподписанных типов.

http://www.postgresql.org/docs/9.4/static/sql-createdomain.html

 CREATE DOMAIN name [ AS ] data_type
    [ COLLATE collation ]
    [ DEFAULT expression ]
    [ constraint [ ... ] ]
 where constraint is:
 [ CONSTRAINT constraint_name ]
 { NOT NULL | NULL | CHECK (expression) }

Домен подобен типу, но с дополнительным ограничением.

Для конкретного примера вы можете использовать

CREATE DOMAIN uint2 AS int4
   CHECK(VALUE >= 0 AND VALUE < 65536);

Вот что дает psql, когда я пытаюсь злоупотреблять типом.

DS1 = # select (346346:: uint2);

ОШИБКА: значение для домена uint2 нарушает ограничение проверки "uint2_check"

Ответ 2

Это не в стандарте SQL, поэтому общее желание его реализовать ниже.

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

Тем не менее, нет причин, по которым это невозможно сделать. Это просто много работы.

Ответ 3

Вы можете использовать ограничение CHECK, например:

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric CHECK (price > 0)
);

Также PostgreSQL имеет serial и bigserial типы для автоматического увеличения.

Ответ 4

У Postgres есть целочисленный тип без знака, о котором многие не знают: OID.

Тип oid в настоящее время реализован как беззнаковое четырехбайтовое целое число. [...]

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

Это не числовой тип, и попытка выполнить какие-либо арифметические (или даже побитовые операции) с ним потерпит неудачу. Кроме того, это всего 4 байта (INTEGER), нет соответствующего 8-байтового (BIGINT) беззнакового типа.

Так что это не очень хорошая идея, чтобы использовать это самостоятельно, и я согласен со всеми другими ответами, что в дизайне базы данных Postgresql вы всегда должны использовать столбец INTEGER или BIGINT для вашего серийного первичного ключа - иметь начало с отрицательного значения (MINVALUE) или разрешить его обтекание (CYCLE), если вы хотите исчерпать весь домен.

Тем не менее, это весьма полезно для преобразования ввода-вывода, например, для миграции с другой СУБД. Вставка значения 2147483648 в столбец целых чисел приведет к "ОШИБКЕ: целое число вне диапазона", тогда как использование выражения 2147483648::OID работает просто отлично.
Аналогично, при выборе целочисленного столбца в виде текста с помощью mycolumn::TEXT вы получите отрицательные значения в определенный момент, но с помощью mycolumn::OID::TEXT вы всегда получите натуральное число.

Смотрите пример на dbfiddle.uk.

Ответ 5

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

https://www.postgresql.org/docs/10/datatype-numeric.html

integer     4 bytes     typical choice for integer  -2147483648 to +2147483647
serial  4 bytes     autoincrementing integer    1 to 2147483647