美好的一天 我在localhost上为网站创建数据库。并提供一些信息,比我从数据库中删除并重新输入信息。现在对于'id'主键我有200多行。我想重新安排主键。
例如
id |name
1 |Samuel
2 |Smith
4 |Gorge
15 |Adam
19 |David
我想拥有
id |name
1 |Samuel
2 |Smith
3 |Gorge
4 |Adam
5 |David
是否可以使用任何命令?
答案 0 :(得分:2)
主键的目的是唯一标识每一行,因此一个表中的行可以与另一个表中的行相关。请记住,这是一个关系数据库,“关系”的部分含义是实体彼此相关。
换句话说,您不希望更改行的主键,因为这会破坏其他表的链接。 MySQL确实不保证插入自动递增的值没有漏洞。事实上,正如您所发现的,删除和重新插入会导致问题。
您将“主键”解释为序列号,而数据库维护的每一行都没有间隙,这是不正确的。
即使您不想这样做,也可以。我建议反对,但你可以:
declare @rn := 0;
update t
set id = (@rn := @rn + 1)
order by id;
如果您想长期强制执行此操作,则需要了解触发器。
答案 1 :(得分:2)
您可以删除主键列并重新创建它。然后将重新分配所有ID,我假设按插入行的顺序。
alter table your_table drop column id;
然后创建它
ALTER TABLE `your_table_name` ADD `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
答案 2 :(得分:1)
考虑这种情况:Gorge发送了一些令人反感的电子邮件,人们抱怨并且他的帐户(#4)被列入黑名单。
然后你重新排序你的主键值,Adam现在被分配了id 4.突然,他发现自己被禁止了!很多人没有理由不信任他。
主键不需要是连续的 - 它们只需要是唯一的。如果有时候ROLLBACK事务或删除行,那么存在间隙是正常的。
答案 3 :(得分:0)
主键很可能是从某种自动增量序列自动生成的。在这种情况下,您可以采取以下步骤:
1)将所有主键更新为序列的下一个值:这会将所有值折叠为连续范围。在您的情况下,这些id
将为20, 21, 22, 23, 24
。 Postgres示例:
UPDATE my_table SET id = nextval(my_table_id_sequence)
2)重置序列以从1开始:在Postgres中,这将如下所示:
ALTER SEQUENCE my_table_id_sequence RESTART WITH 1
3)再次将值更新为序列的下一个值:现在可以将所有行“向下”移回“1”,在您的情况下,它们将为{{1} }。在重置之前首先合并序列“顶部”的所有值非常重要,因为这样我们可以保证在“底部”不会发生任何主键冲突
1, 2, 3, 4, 5
注意:此方法仅在没有引用表的主键的foriegn键时才有效。如果有外键,您仍然可以采用相同的方法,但首先执行以下3个步骤:
1)查找引用此主键列的所有相关表/列
2)创建一个功能,将pk的更新级联到所有fks
3)创建一个触发器,每当pk更新时执行上述功能:此时,当我们更新主键列时,所有相关的外键也将被更新。根据数据库的不同,您可能需要显式推迟约束验证,或者在一个事务中执行整个操作。
有关Postgres上述内容的示例,您可以在此处查看我的答案How Do I Deep Copy a Set of Data, and Change FK References to Point to All the Copies?