因为主键(标识符)不会低于0,我想它应该总是未签名的?
答案 0 :(得分:48)
TL / DR:是的,但几乎没关系。
自动增量总是增加,因此永远不会使用负值。您也可以将其设为无符号,并获得两倍的值。
另一方面,如果您的表使用2 31 值,它可能会在短时间内使用2 32 值,因此具有两倍的值范围没有太大的区别。无论如何,你必须升级到BIGINT。
MySQL支持可选的SERIAL
数据类型(可能是为了与PostgreSQL兼容,因为SERIAL
不是标准的ANSI SQL)。此数据类型只是创建BIGINT UNSIGNED
的简写。
继续尝试:
CREATE TABLE test.foo (foo_id SERIAL PRIMARY KEY);
SHOW CREATE TABLE test.foo;
CREATE TABLE `test`.`foo` (
`foo_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`foo_id`),
UNIQUE KEY `foo_id` (`foo_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
无论是声明有符号还是无符号整数,都会获得相同数量的不同值:INT
为2 32 ,{{1>为2 64 1}}。如果数字是无符号的,则获得从0到最大值减去1的值。如果该号码已签名,则您会获得从BIGINT
到-max/2
的值。无论哪种方式,您都可以获得相同的绝对值绝对值。
但是由于max/2-1
默认从零开始并且在正方向上递增,因此利用正值比使用负值更方便。
但是,获得2倍的正值并不重要。任何超过最大有符号整数值2 31 -1的表都可能会继续增长,因此您应该只为这些表使用AUTO_INCREMENT
。
你真的,真的,真的不太可能分配超过2个 63 -1个主键值,即使你删除所有行并重新加载它们一天很多次。
答案 1 :(得分:6)
为什么你认为主键不会低于0?那不是一个给定的。我认为你把它与标识栏混淆了。
在任何情况下,它都不会产生明显的差异,无论是否是主键,都要将数据类型映射到列中预期的数据类型。
答案 2 :(得分:3)
否 - 主键不会总是无符号,例如:
create table user_status
(
status_id tinyint not null primary key,
name varchar(64) not null,
msg varchar(255) default null
)engine=innodb;
insert into user_status values
(-99,'banned', 'Account banned'),
(-2,'closed', 'Account closed'),
(-1,'unverified', 'Account not verified'),
(0,'suspended','Account suspended'),
(1,'active', null);
如果这是一个订单表,但我会使用order_id int unsigned
答案 3 :(得分:2)
因为主键(标识符)不会低于0
我从该声明中假设您的主键也会自动递增。
如果确实如此,那么确保您的列无符号是非常明智的,原因是MySQL manual:
仅当AUTO_INCREMENT列仅包含正值时,它才能正常工作。插入负数被视为插入一个非常大的正数。这样做是为了避免数字从正到负“包裹”时的精度问题,并确保您不会意外地获得包含0的AUTO_INCREMENT列。
如果要将负数插入自动递增列,那么您可能错误地解决了问题。