如何重新安排数据库主键

时间:2014-02-01 18:50:27

标签: mysql

美好的一天 我在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

是否可以使用任何命令?

4 个答案:

答案 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?