2009-04-11 6 views
103

У меня есть таблица MySQL с первичным ключом автоматического увеличения. Я удалил несколько строк в середине таблицы. Теперь у меня, например, что-то вроде этого в столбце ID: 12, 13, 14, 19, 20. Я удалил строки 15, 16, 17 и 18.Переназначение/возврат автоматического приращения первичного ключа

Я хочу переназначить/переустановить/изменить порядок первичного ключа, чтобы у меня была непрерывность, т. Е. Сделайте 19 a 15, 20 a 16 и так далее.

Как я могу это сделать?

ответ

76

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

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

+0

У меня есть другие таблицы, которые содержат внешний ключ для этой таблицы, но я только начинаю проект, так что это нормально для меня .. Спасибо! – Jonathan

+54

Возможно, было бы лучше, если вы попытаетесь начать принимать, что ваши идентификаторы не всегда будут последовательными, иначе, когда вы начнете работать над большими проектами, это будет действительно изгонять! –

+3

ALTER TABLE your_table AUTO_INCREMENT = 1 – Sinac

28

Вы можете просто использовать этот запрос

alter table abc auto_increment = 1; 
+1

В этом случае это не сработает. Для таблиц ISAM значение autoinc будет установлено на max (id) + 1. Для InnoDB он ничего не сделает. См. Alter table docs для изменения AUTOINCREMENT http://dev.mysql.com/doc/refman/5.0/en/alter-table.html – lreeder

+3

@Ireeder с 5,6 года поведение для innodb аналогично поведению myisam – Anshul

46

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

ALTER TABLE `users` DROP `id`; 
ALTER TABLE `users` AUTO_INCREMENT = 1; 
ALTER TABLE `users` ADD `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST; 
+5

, это отлично подходит для Таблицы MyISAM. спасибо! – gillyspy

+0

На таблице MyISAM с 584 тыс. Строк это заняло около 7,3 секунды. – user1278519

+3

Если бы у меня было 100 голосов, я бы проголосовал за это все время, так как он разбивает заявления sql для нуба, подобного мне, который помогает понять – repzero

294

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

SET @count = 0; 
UPDATE `users` SET `users`.`id` = @count:= @count + 1; 

Если столбец используется в качестве внешнего ключа в других таблицах, убедитесь, что вы используете ON UPDATE CASCADE вместо стандартного ON UPDATE NO ACTION для внешнего ключа отношения в этих таблицах.

Кроме того, чтобы сбросить счет AUTO_INCREMENT, вы можете немедленно выпустить следующую инструкцию.

ALTER TABLE `users` AUTO_INCREMENT = 1; 

Для MySQLs он будет сбросить значение для MAX(id) + 1.

+0

Это с внешними ключами - очень крутое решение для моей таблицы, где много мусора вставляется и удаляется, и я хочу сохранить индексное пространство. – mukunda

+1

mySQL Doc рекомендует: «Как правило, кроме инструкций SET вы никогда не должны присваивать значение переменной пользователя и читать значение в пределах одного и того же оператора.Например, чтобы увеличить переменную, это нормально: SET @a = @a + 1; Для других утверждений, таких как SELECT, вы можете получить ожидаемые результаты, но это не гарантируется. В следующем утверждении вы можете подумать, что MySQL сначала оценит @a, а затем выполнит второе занятие: SELECT @a, @a: = @ a + 1, ...; Однако порядок оценки выражений с использованием пользовательских переменных не определен. " – ReverseEMF

+3

@ReverseEMF: Нет. Порядок присваивания фиксирован в выражениях MySQL. Из того, что вы цитировали, советы по документации MySQL против множественного независимого использования переменной. В вышеприведенном случае оценка выражения обязательно произойдет в предопределенной из-за одного выражения присваивания '' users'. 'id' = @count: = @count + 1'. Из документации: «Значение в правой части может быть буквальным значением, другая переменная, сохраняющая значение, или любое юридическое выражение, которое дает скалярное значение « – Anshul

12

Или, из PhpMyAdmin, удалите флаг «AutoIncrement», сохраните, установите его снова и сохраните. Это сбрасывает его.

8
SET @num := 0; 

UPDATE your_table SET id = @num := (@num+1); 

ALTER TABLE your_table AUTO_INCREMENT =1; 

Я думаю, что это будет делать это

0

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

$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0); 
$viewsrowsdata = mysql_query(" 
    SELECT `rank`, `field1`, `field2`, `field3`, `field4` 
     FROM (SELECT (@rank:[email protected]+1) as `rank`, `field1`, `field2`, `field3`, `field4` 
      FROM (SELECT * FROM `views`) a 
      CROSS JOIN (SELECT @rank:=0) b 
      ORDER BY rank ASC) c 
"); 
while ($row = mysql_fetch_assoc($viewsrowsdata)) { 
    $data[] = $row; 
} 
foreach ($data as $row) { 
    $new_field_1 = (int)$row['rank']; 
    $old_field_1 = (int)$row['field1']; 
    mysql_query("UPDATE `table` SET `field_1` = $new_field_1 WHERE `field_1` = $old_field_1"); 
} 
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')"); 

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

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

$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0); 
$viewsrowsdata = mysql_query("SELECT * FROM `table`"); 
$updated_key = 0; 
while ($row = mysql_fetch_assoc($viewsrowsdata)) { 
    $data[] = $row; 
} 
foreach ($data as $row) { 
    $updated_key = $updated_key + 1; 
    mysql_query("UPDATE `table` SET `field_1` = '$updated_key' WHERE `field_1` = '$row['field_1']'"); 
} 
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')"); 
0

для InnoDB, это сделать (это удалит все записи из таблицы, сделать bakcup первым):

SET @[email protected]@CHARACTER_SET_RESULTS ; 
SET @[email protected]@COLLATION_CONNECTION ; 
SET NAMES utf8 ; 
SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 ; 
SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 ; 
SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' ; 
SET @[email protected]@SQL_NOTES, SQL_NOTES=0 ; 
/* ================================================= */ 

drop table tablename; 
CREATE TABLE `tablename` (
    table structure here! 

) ENGINE=InnoDB AUTO_INCREMENT= ai number to reset DEFAULT CHARSET= char set here; 



/* ================================================= */ 
SET [email protected]_SQL_MODE ; 
SET [email protected]_FOREIGN_KEY_CHECKS ; 
SET [email protected]_UNIQUE_CHECKS ; 
SET [email protected]_CHARACTER_SET_CLIENT ; 
SET [email protected]_CHARACTER_SET_RESULTS ; 
SET [email protected]_COLLATION_CONNECTION ; 
SET [email protected]_SQL_NOTES ; 
-1

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

Вы также можете просто использовать случайное значение или значение MD5. Все эти варианты имеют свои преимущества, особенно на ИТ-сек. числовые идентификаторы легко перечислить.

+0

... На чем вы основываете это? Возможно, просто не делайте такие страницы, как «complete_user_info_export.php? Userid = 34»? Внутреннее использование строки или другого случайного значения в качестве индекса/идентификатора - это плохая идея Это создает больше проблем, чем решает (если он даже решает какие-либо проблемы) –

0

меня были те же сомнения, но не может делать какие-либо изменения на столе, я решил делать следующее, увидев мое удостоверение личности не превышало максимальное количество выставиться в переменной @count:

SET @count = 40000000; 
UPDATE `users` SET `users`.`id` = @count:= @count + 1; 

SET @count = 0; 
UPDATE `users` SET `users`.`id` = @count:= @count + 1; 

ALTER TABLE `users` AUTO_INCREMENT = 1; 

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

0

Лучший выбор - изменить столбец и удалить атрибут auto_increment. Затем выпустите другой оператор alter и поместите auto_increment обратно в столбец. Это сбросит счет до максимального + 1 текущих строк и, таким образом, сохранит ссылки на внешние ключи обратно в эту таблицу, из других таблиц в вашей базе данных или любого другого использования ключа для этого столбца.

1

в PHPMyAdmin

note: this will work if you delete last rows not middle rows.

Гото ваш table-> нажмите на операции меню-> Гото таблица options-> изменение AUTO_INCREMENT в том, что не от того, где вы хотите начать.

ваш автоинкремент для стола начинайте с этого нет.

попробуйте. enter image description here

Смежные вопросы