我看到了这篇帖子(MySQL中tinyint、smallint、mediumint、bigint和int的区别是什么?),意识到PostgreSQL不支持无符号整数。
有人能解释一下为什么吗?
大多数时候,我在MySQL中将无符号整数用作自增的主键。在这样的设计中,当我将数据库从MySQL迁移到PostgreSQL时,该如何克服这个问题?
谢谢。
我看到了这篇帖子(MySQL中tinyint、smallint、mediumint、bigint和int的区别是什么?),意识到PostgreSQL不支持无符号整数。
有人能解释一下为什么吗?
大多数时候,我在MySQL中将无符号整数用作自增的主键。在这样的设计中,当我将数据库从MySQL迁移到PostgreSQL时,该如何克服这个问题?
谢谢。
这并不在SQL标准中,因此实现它的一般愿望较低。
拥有过多不同的整数类型会使类型解析系统变得更加脆弱,因此添加更多类型会受到一定的抵制。
尽管如此,没有理由不能这样做。只是需要大量的工作。
to_char
模式。 - Bergi已经回答了为什么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);
ERROR: value for domain uint2 violates check constraint "uint2_check"
你可以使用CHECK约束,例如:
CREATE TABLE products (
id integer,
name text,
price numeric CHECK (price > 0)
);
此外,PostgreSQL 还有 serial
、smallserial
和 bigserial
类型来实现自增。
2^32-1
,而有符号整数只能达到2^31-1
。 - JukesOnYouNULL
和CHECK
是完全正交的。您可以有带有或不带有CHECK
的NULL
/NOT NULL
列。只需注意,根据https://www.postgresql.org/docs/9.4/ddl-constraints.html中的文档,返回`NULL`的`CHECK`将计算为TRUE,因此如果您真的想要防止NULL,则应改用`NOT NULL(或除
CHECK`之外) 。 - flaviovsinteger
中(至少不能让它们随机变为正数或负数..)。 - hanshenrik这里是如何实现一个简单的无符号int8:
首先我将使用
CREATE TYPE name (
INPUT = uint8_in,
OUTPUT = uint8_out
[, RECEIVE = uint8_receive ]
[, SEND = uint8_send ]
[, ANALYZE = uint8_analyze ]
, INTERNALLENGTH = 8
, PASSEDBYVALUE ]
, ALIGNMENT = 8
, STORAGE = plain
, CATEGORY = N
, PREFERRED = false
, DEFAULT = null
)
我必须首先定义的是最小的两个函数uint8_in
和uint8_out
。
CREATE FUNCTION uint8_in(cstring)
RETURNS uint8
AS 'uint8_funcs'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION uint64_out(complex)
RETURNS cstring
AS 'uint8_funcs'
LANGUAGE C IMMUTABLE STRICT;
PG_FUNCTION_INFO_V1(complex_in);
Datum complex_in(PG_FUNCTION_ARGS) {
char *str = PG_GETARG_CSTRING(0);
uint64_t result;
if(sscanf(str, "%llx" , &result) != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for uint8: \"%s\"", str)));
return (Datum)SET_8_BYTES(result);
}
嗯,或者你可以直接找已经完成的。
integer 4 bytes typical choice for integer -2147483648 to +2147483647
serial 4 bytes autoincrementing integer 1 to 2147483647
OID
。
虽然它不是数字类型,但尝试对其进行任何算术运算(甚至是按位运算)都会失败。此外,它只有4个字节(
oid
类型当前实现为无符号四字节整数。[...]
oid
类型本身除了比较操作外几乎没有其他操作。但是,它可以转换为整数,然后使用标准整数运算符进行操作(如果这样做,请注意可能存在的有符号与无符号混淆)。
INTEGER
),没有相应的8个字节(BIGINT
)无符号类型。INTEGER
或BIGINT
列——如果您想要耗尽完整域,则使其从负数(MINVALUE
)开始或允许其环绕(CYCLE
)。2147483648
插入整数列将导致"ERROR: integer out of range",而使用表达式2147483648::OID
则完全可以。mycolumn::OID::TEXT
,您将始终获得自然数。
serial
(1到2147483647)或者bigserial
(1到9223372036854775807)。一个带符号的64位整数可能提供了足够的空间。 - mu is too short