主键应该始终是未签名的?

时间:2010-04-21 21:48:42

标签: mysql database

因为主键(标识符)不会低于0,我想它应该总是未签名的?

4 个答案:

答案 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列。

如果要将负数插入自动递增列,那么您可能错误地解决了问题。