первичный ключ всегда должен быть без знака? - PullRequest
42 голосов
/ 22 апреля 2010

поскольку первичный ключ (идентификатор) не будет меньше 0, я думаю, он всегда должен быть без знака?

Ответы [ 4 ]

50 голосов
/ 22 апреля 2010

TL / DR: Да, но это почти не имеет значения.

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

С другой стороны, если ваша таблица использует 2 31 значений, она, вероятно, также будет использовать 2 32 значений за короткое время, поэтому двойной диапазон значений isn ' большая разница. В любом случае вам придется перейти на 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 

Вы получаете одинаковое количество различных значений независимо от того, объявляете ли вы целое число со знаком или без знака: 2 32 для INT и 2 64 для BIGINT. Если число без знака, вы получаете значения от 0 до этого максимального значения минус один. Если число подписано, вы получаете значения от -max/2 до max/2-1. В любом случае вы получаете одинаковое абсолютное количество различных значений.

Но поскольку AUTO_INCREMENT начинается с нуля по умолчанию и увеличивается в положительном направлении, удобнее использовать положительные значения, чем отрицательные.

Но вряд ли имеет значение, что вы получаете в 2 раза больше положительных значений. Любая таблица, которая будет превышать максимальное целочисленное значение со знаком 2 31 -1, вероятно, будет продолжать расти, поэтому вам следует просто использовать BIGINT для этих таблиц.

Вы действительно, действительно, действительно вряд ли выделите более 2 63 -1 значений первичного ключа, даже если вы удалите все свои строки и повторно загрузите их много раз день.

6 голосов
/ 22 апреля 2010

Почему именно вы предполагаете, что первичный ключ не будет меньше 0? Это не дано. Я думаю, что вы путаете это с колонкой идентификации.

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

3 голосов
/ 22 апреля 2010

НЕТ - первичный ключ не всегда будет без знака, например:

 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

2 голосов
/ 17 июня 2016

, поскольку первичный ключ (идентификатор) не будет меньше 0

. Из этого утверждения я предполагаю, что ваш первичный ключ также автоматически увеличивается.

Если это так,тогда очень разумно убедиться, что ваш столбец не подписан, по причине, описанной в руководстве MySQL :

Столбец AUTO_INCREMENT работает должным образом, только если он содержит только положительные значения.Вставка отрицательного числа считается вставкой очень большого положительного числа.Это сделано для того, чтобы избежать проблем с точностью, когда числа «переворачиваются» с положительных на отрицательные, а также для того, чтобы случайно не получить столбец AUTO_INCREMENT, который содержит 0.

Если вы вставляете отрицательные числа вавтоинкрементный столбец, то вы, вероятно, решаете проблему неправильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...