将PostgreSQL的主键重置为1

110

如何在已有数据的情况下将PostgreSQL表的主键重置为从1开始生成?

当前主键从1000000开始生成,我希望将其重置为从1开始,同时保留现有数据。

6个回答

250

将序列重置为1并重新开始的最佳方法是执行以下操作:

ALTER SEQUENCE <tablename>_<id>_seq RESTART WITH 1

例如,对于users表,应该是这样的:

ALTER SEQUENCE users_id_seq RESTART WITH 1

30
WITH 1参数是冗余的,可以省略。 - Jacek Krawczyk
这是唯一正确的答案,因为它确实重置了序列。 - Balbinator
2
自动生成的CREATE TABLE子句索引的大问题是我们不知道名称(后缀也可能不是seq,而是pk等)。但是在psql上通过\d my_table_name很容易解决。或者通过SQL查询,SELECT * FROM pg_indexes WHERE tablename like '%my_table_name%' - Peter Krauss
2
刚刚在解决这个问题上费了好大的劲。如果表中有数据,并且您希望从上次离开的地方开始,仍然需要传递 WITH 1 或者省略它。如果您指定了 WITH 123 或任何当前最高值,它将把该值添加到下一行。这可能不是您想要的结果。 - Owen Allen
1
我需要在序列标识符前加上模式名称,否则会出现“关系'tablename_id_seq'不存在”的错误。可以通过“\d <tablename>”查找此命名约定以及id列的默认值(nextval...)。因此,在我的情况下,本质上是ALTER SEQUENCE auth.roles_id_seq RESTART WITH 5; - JackLeEmmerdeur

40

查看更好的选项,请点击此链接:https://dev59.com/am865IYBdhLWcg3wa-A0#5272164

自增主键(即数据类型为 serial primary key 的列)与一个序列相关联。您可以使用 setval(<seqname>, <next_value>) 函数设置任何序列的下一个值。请注意,要执行该函数本身,您需要使用SELECT,例如: SELECT setval(<seqname>, <next_value>)

当使用serial时,自动创建的序列名称为 <table>_<column>_seq


14
你需要在调用前加上 "SELECT",例如:SELECT setval('table_id_seq', 10000) - Tom
5
如果我执行SELECT setval('table_id_seq', 1),当我插入新记录时,id的值会变成2而不是1。Paweł Gościcki的解决方案可行。(PostgreSQL 9.3) - bluish
@bluish 可能发生的情况是在分配新的主键之前,序列号已经增加了,即需要将其重置为0。但无论如何,我同意其他解决方案更好。 - kralyk

16

TRUNCATE TABLE table_name RESTART IDENTITY;

这将删除所有数据。

也许有些用户和我一样需要这个操作。


1
你刚刚复制粘贴了这个命令,却没有警告用户它将删除表中的所有行,这使得它成为一个非常糟糕的“答案”。坦白地说,它应该被删除。如果可以的话,我会给它更多的负评。 - code_dredd

5

@bluish实际上,使用自增主键插入新记录,就像明确使用序列一样:

INSERT INTO MyTable (id, col1, ...) VALUES (MySeq.nextval(), val1, ...)

因此,如果你想让第一个id为1,你需要将序列设置为0。但是这超出了范围,所以你必须使用ALTER SEQUENCE语句。例如,如果你的表menu中有一个名为number的序列字段:

ALTER SEQUENCE menu_number_seq RESTART

将使工作完美。


0
首先,清空表格,然后重置主键。
假设您有一个名为population的表格。 delete from population ALTER SEQUENCE population_id_seq" RESTART WITH 1

-1

@ZootHii TRUNCATE TABLE table_name RESTART IDENTITY CASCADE;

删除表table_name并重置自增ID,同时级联删除关联表数据。


这并没有提供问题的答案。如果要批评或请求作者澄清,请在他们的帖子下留言。-【来自审查】 - helvete
和我给ZootHii的回复一样:你刚刚复制粘贴了这个命令,却没有警告用户它将删除表中的所有行,这使得它成为一个非常糟糕的“答案”。但是这个更糟糕,因为它会级联删除依赖于它的其他表的数据(例如通过外键)。再次强调,这是另一个应该被删除的“答案”。如果可以的话,我会给它更多的负评。 - code_dredd
首先,如果尝试截断一个存在关系的表,将不允许进行截断。 - Thangaraj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接