重新排序/重置自动递增主键

5jvtdoz2  于 2021-06-15  发布在  Mysql
关注(0)|答案(15)|浏览(347)

我有一个带有自动递增主键的mysql表。我删除了表格中间的一些行。例如,我在id列中有这样的内容:12,13,14,19,20。我删除了15、16、17和18行。
我想重新分配/重置/重新排序主键,这样我就有了连续性,也就是说,使19 a 15,20 a 16,依此类推。
我该怎么做?

uqdfh47h

uqdfh47h1#

您可以删除主键列并重新创建它。然后,应按顺序重新分配所有ID。
然而,在大多数情况下,这可能是一个坏主意。如果有其他表对此表具有外键,那么它肯定不起作用。

c6ubokkw

c6ubokkw2#

您也可以简单地避免使用数字id作为主键。如果表包含国家/地区信息,则可以使用国家/地区代码作为主id;如果表包含文章,则可以使用永久链接。
也可以简单地使用随机值或md5值。所有这些选择都有它自己的好处,特别是在it上。数字标识很容易枚举。

4zcjmb1e

4zcjmb1e3#

这起作用-https://stackoverflow.com/a/5437720/10219008.....but 如果你遇到一个问题'错误代码:1265。第1行“id”列的数据被截断…然后运行以下操作。在更新查询中添加忽略。

SET @count = 0;
set sql_mode = 'STRICT_ALL_TABLES';
UPDATE IGNORE web_keyword SET id = @count := (@count+1);
zpjtge22

zpjtge224#

您可以删除该列的主键自动递增功能,然后每次更新该列时,先运行一个查询,该查询将对表中的所有行进行计数,然后运行一个循环,遍历该行计数,并将每个值插入相应的行中,最后运行一个查询,插入新行,该列的值为总行数加1。这将完美的工作,是最绝对的解决方案,有人试图完成你是什么。以下是可用于函数的代码示例:

$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:=@rank+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')");

在这里,我创建了一个关联数组,我在select查询中的一个rank列上附加了这个数组,它给每一行一个从1开始的rank值。然后我遍历关联数组。
另一个选项是获取行计数,运行一个基本的select查询,获取关联数组并以相同的方式对其进行迭代,但是添加一个变量,该变量会在每次迭代中更新。这是不太灵活,但将完成同样的事情。

$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')");
dzhpxtsq

dzhpxtsq5#

最好的选择是更改列并删除auto\u increment属性。然后发出另一个alter语句并将auto\ u increment放回该列。这会将计数重置为当前行的最大值+1,从而保留从数据库中的其他表或该列的任何其他键用法返回到此表的外键引用。

n8ghc7c1

n8ghc7c16#

我的意见是创建一个名为row\u order的新列。然后对该列重新排序。我不接受对主键的更改。作为一个例子,如果order列是banner\u position,我已经做了这样的事情,这是为了删除,更新,创建banner position列。调用此函数分别对它们重新排序。

public function updatePositions(){
    $offers = Offer::select('banner_position')->orderBy('banner_position')->get();
    $offersCount = Offer::max('banner_position');
    $range = range(1, $offersCount);

    $existingBannerPositions = [];
    foreach($offers as $offer){
        $existingBannerPositions[] = $offer->banner_position;
    }
    sort($existingBannerPositions);
    foreach($existingBannerPositions as $key => $position){
        $numbersLessThanPosition = range(1,$position);
        $freshNumbersLessThanPosition = array_diff($numbersLessThanPosition, $existingBannerPositions);
        if(count($freshNumbersLessThanPosition)>0) {
            $existingBannerPositions[$key] = current($freshNumbersLessThanPosition);
            Offer::where('banner_position',$position)->update(array('banner_position'=> current($freshNumbersLessThanPosition)));
        }
    }
}
tzxcd3kk

tzxcd3kk7#

即使这个问题似乎很老,将张贴一个答案的人谁达到在这里搜索。

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 .

6jygbczu

6jygbczu8#

SELECT * from `user` ORDER BY `user_id`; 

SET @count = 0;

UPDATE `user`  SET `user_id` = @count:= @count + 1;

ALTER TABLE `user_id` AUTO_INCREMENT = 1;

如果你想的话 order by

xv8emn3q

xv8emn3q9#

对于innodb,这样做(这将从表中删除所有记录,首先生成一个bakcup):

SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS ;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION ;
SET NAMES utf8 ;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 ;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 ;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' ;
SET @OLD_SQL_NOTES=@@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 SQL_MODE=@OLD_SQL_MODE ;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS ;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS ;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT ;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS ;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION ;
SET SQL_NOTES=@OLD_SQL_NOTES ;
niknxzdl

niknxzdl10#

或者,从phpmyadmin中,删除“autoincrement”标志,保存,再次设置并保存。这将重置它。

ubby3x7f

ubby3x7f11#

您可以简单地使用这个查询

alter table abc auto_increment = 1;
yyhrrdl8

yyhrrdl812#

为了重置用户表的id,我使用以下sql查询。上面说过这会破坏你和其他table的关系。

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;
wlzqhblo

wlzqhblo13#

SET  @num := 0;

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

ALTER TABLE your_table AUTO_INCREMENT =1;

我想这样就行了

tjvv9vkg

tjvv9vkg14#

在phpmyadmin中
注意:如果删除的是最后一行而不是中间行,这将起作用。
转到您的表格->单击操作菜单->转到表格选项->将自动增量更改为从您要开始的位置开始的编号。
你的表从那个数字开始自动递增。
试试看。

tkqqtvp1

tkqqtvp115#

我也有同样的疑问,但无法对表进行任何更改,我决定执行以下操作,因为我的id没有超过变量@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;

解决方案需要,但它是安全的,而且是必要的,因为我的表拥有外键,而数据在另一个表中。

相关问题