如何重置postgres中的序列并用新数据填充id列?

sen*_*nin 108 postgresql sequence

我有一张超过一百万行的表.我需要重置序列并用新值重新分配id列(1,2,3,4 ...等...).有没有简单的方法呢?

Mic*_*ker 175

如果您不想保留ID的顺序,那么您可以

ALTER SEQUENCE seq RESTART WITH 1;
UPDATE t SET idcolumn=nextval('seq');
Run Code Online (Sandbox Code Playgroud)

我怀疑有一种简单的方法可以按照您选择的顺序执行此操作,而无需重新创建整个表格.

  • 这可能会导致重复的ID.为了防止这种情况,您可以先将所有值设置为非常高的值:UPDATE t SET idcolumn = 1000000 + nextval('seq'); 然后运行上面的脚本. (5认同)
  • 不应该是'ALTER SEQUENCE seq RESTART WITH 1;`? (4认同)
  • `SELECT setval('seq',1,FALSE)`应该做同样的事情(这里,第三个参数,FALSE,做魔术,因为它表明`nextval`必须是1而不是2) (4认同)

Oli*_*ver 39

使用PostgreSQL 8.4或更新版本时,无需再指定WITH 1.将使用由CREATE SEQUENCE最后设置或最后设置的起始值ALTER SEQUENCE START WITH(最可能是1).

重置序列:

ALTER SEQUENCE seq RESTART;
Run Code Online (Sandbox Code Playgroud)

然后更新表的ID列:

UPDATE foo SET id = DEFAULT;
Run Code Online (Sandbox Code Playgroud)

来源:PostgreSQL文档

  • 也是我的案例的最佳答案。我将这个答案与[this](/sf/ask/373970831/)结合起来,它解释了 ALTER SEQUENCE 命令......所以我改变了“seq”通过 ***mytable_id_seq*** 其中“mytable”是我的表名称,“id”是我的串行列的名称 (3认同)
  • 这似乎是最好的答案,因为它避免了对序列起始值的假设。 (2认同)

Fra*_*ens 38

重置序列:

SELECT setval('sequence_name', 0);
Run Code Online (Sandbox Code Playgroud)

更新当前记录:

UPDATE foo SET id = DEFAULT;
Run Code Online (Sandbox Code Playgroud)

  • 序列的最小值可能大于0。(而“ serial”和“ CREATE SEQUENCE”类型使用的默认最小值为1!) (2认同)

ivy*_*ivy 16

两者都提供的解决方案对我不起作用;

> SELECT setval('seq', 0);
ERROR:  setval: value 0 is out of bounds for sequence "seq" (1..9223372036854775807)
Run Code Online (Sandbox Code Playgroud)

setval('seq', 1)用2开始编号,并用2 ALTER SEQUENCE seq START 1开始编号,因为seq.is_called为真(Postgres版本9.0.4)

对我有用的解决方案是:

> ALTER SEQUENCE seq RESTART WITH 1;
> UPDATE foo SET id = DEFAULT;
Run Code Online (Sandbox Code Playgroud)


Ali*_*ani 13

只是为了简化和澄清ALTER SEQUENCESELECT setval的正确用法以重置序列:

ALTER SEQUENCE sequence_name RESTART WITH 1;
Run Code Online (Sandbox Code Playgroud)

相当于

SELECT setval('sequence_name', 1, FALSE);
Run Code Online (Sandbox Code Playgroud)

无论是陈述的,可以使用重置序列,你可以得到由NEXTVAL("SEQUENCE_NAME")的下一个值规定在这里也:

nextval('sequence_name')
Run Code Online (Sandbox Code Playgroud)


jah*_*d31 9

重置序列以使用数字1重新开始的最佳方法是执行以下操作:

ALTER SEQUENCE <tablename>_<id>_seq RESTART WITH 1
Run Code Online (Sandbox Code Playgroud)

因此,例如对于users表,它将是:

ALTER SEQUENCE users_id_seq RESTART WITH 1
Run Code Online (Sandbox Code Playgroud)


小智 8

SELECT SETVAL('seq_my_table_pk_id', (SELECT MAX(my_table_pk_id) + 1 FROM my_table));
Run Code Online (Sandbox Code Playgroud)


Sto*_*one 5

仅供参考:如果您需要在 ID 范围(例如 256 - 10000000)之间指定新的起始值:

SELECT setval('"Sequence_Name"', 
       (SELECT coalesce(MAX("ID"),255) 
           FROM "Table_Name" 
           WHERE "ID" < 10000000 and "ID" >= 256)+1
       ); 
Run Code Online (Sandbox Code Playgroud)


ale*_*sky 5

要保留行的顺序:

UPDATE thetable SET rowid=col_serial FROM 
(SELECT rowid, row_number() OVER ( ORDER BY lngid) AS col_serial FROM thetable ORDER BY lngid) AS t1 
WHERE thetable.rowid=t1.rowid;
Run Code Online (Sandbox Code Playgroud)


小智 5

仅重置序列并更新所有行可能会导致重复的 id 错误。在许多情况下,您必须将所有行更新两次。首先使用更高的 id 以避免重复,然后使用您真正想要的 id。

请避免向所有 ID 添加固定金额(如其他评论中建议的那样)。如果行数多于这个固定数量,会发生什么情况?假设序列的下一个值高于现有行的所有 id(您只想填补空白),我会这样做:

UPDATE table SET id = DEFAULT;
ALTER SEQUENCE seq RESTART;
UPDATE table SET id = DEFAULT;
Run Code Online (Sandbox Code Playgroud)


Die*_*ezú 5

就我而言,我通过以下方式实现了这一目标:

ALTER SEQUENCE table_tabl_id_seq RESTART WITH 6;
Run Code Online (Sandbox Code Playgroud)

我的表的名称为table

  • 感谢您提供带有表名的具体示例。其他答案有点太模棱两可了。 (2认同)

小智 5

在我的例子中,导入错误的 sql 文件后,所有表中的序列都已损坏。SELECT nextval('table_name_id_seq');返回的值小于id列的最大值。因此,我创建了 sql 脚本来恢复每个表的所有序列:

DO
$$
DECLARE
   rec  record;
   table_seq text;
BEGIN
   FOR rec IN
      SELECT *
      FROM   pg_tables
      WHERE  tablename NOT LIKE 'pg\_%'
      ORDER  BY tablename
   LOOP
      table_seq := rec.tablename || '_id_seq';
     
      RAISE NOTICE '%', table_seq;
      EXECUTE format(E'SELECT setval(\'%I\', COALESCE((SELECT MAX(id)+1 FROM %I), 1), false);',
            table_seq, rec.tablename);
      
   END LOOP;
END
$$;
Run Code Online (Sandbox Code Playgroud)

注意:如果您的任何表上都没有该id列,您可以更新逻辑或根据上述逻辑单独处理它们。