如何在postgres中重新设置序列并用新数据填充id列?
我有一个超过100万行的表。 我需要重新设置序列,并重新分配id列的新值(1,2,3,4 …等等)。 有没有简单的方法来做到这一点?
如果你不想保留ID的顺序,那么你可以
ALTER SEQUENCE seq RESTART WITH 1; UPDATE t SET idcolumn=nextval('seq');
我怀疑有一个简单的方法可以按照您select的顺序来完成,而不需要重新创build整个表格。
重置序列:
SELECT setval('sequence_name', 0);
更新当前logging:
UPDATE foo SET id = DEFAULT;
使用PostgreSQL 8.4或更新版本,不需要再指定WITH 1
。 将使用由CREATE SEQUENCE
logging的起始值或最后由ALTER SEQUENCE START WITH
设置的起始值(最可能是1)。
重置序列:
ALTER SEQUENCE seq RESTART;
然后更新表格的ID列:
UPDATE foo SET id = DEFAULT;
来源: PostgreSQL文档
两个提供的解决scheme都不适合我;
> SELECT setval('seq', 0); ERROR: setval: value 0 is out of bounds for sequence "seq" (1..9223372036854775807)
setval('seq', 1)
以2开始编号,并且ALTER SEQUENCE seq START 1
开始编号为2,因为seq.is_called为true(Postgres版本9.0.4)
为我工作的解决scheme是:
> ALTER SEQUENCE seq RESTART WITH 1; > UPDATE foo SET id = DEFAULT;
仅供参考:如果您需要在一系列ID(例如256 – 10000000)之间指定新的开始值:
SELECT setval('"Sequence_Name"', (SELECT coalesce(MAX("ID"),255) FROM "Table_Name" WHERE "ID" < 10000000 and "ID" >= 256)+1 );
要保留行的顺序:
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;
只是为了简化和阐明正确使用ALTER SEQUENCE和SELECT setval来重置序列:
ALTER SEQUENCE sequence_name RESTART WITH 1;
相当于
SELECT setval('sequence_name', 1, FALSE);
这两种语句都可以用来重置序列,你也可以通过nextval('sequence_name')得到下一个值,如下所述:
nextval('sequence_name')
只需重置序列并更新所有行可能会导致重复的id错误。 在许多情况下,您必须更新所有行两次。 先用更高的ID来避免重复,然后用你真正想要的ID。
请避免为所有ID添加固定金额(如其他评论所build议的)。 如果你有更多的行比这个固定的数额会发生什么? 假设序列的下一个值高于现有行的所有id(你只是想填补空白),我会这样做:
UPDATE table SET id = DEFAULT; ALTER SEQUENCE seq RESTART; UPDATE table SET id = DEFAULT;
受到其他答案的启发,我创build了一个SQL函数来进行序列迁移。 该函数将主键序列移至以现有序列范围内部或外部的任何值(> = 1)开始的新连续序列。
我在这里解释了如何在具有相同模式但不同值的两个数据库迁移到一个数据库中时使用此function。
首先,函数(它打印生成的SQL命令,以便清楚实际发生的事情):
CREATE OR REPLACE FUNCTION migrate_pkey_sequence ( arg_table text , arg_column text , arg_sequence text , arg_next_value bigint -- Must be >= 1 ) RETURNS int AS $$ DECLARE result int; curr_value bigint = arg_next_value - 1; update_column1 text := format ( 'UPDATE %I SET %I = nextval(%L) + %s' , arg_table , arg_column , arg_sequence , curr_value ); alter_sequence text := format ( 'ALTER SEQUENCE %I RESTART WITH %s' , arg_sequence , arg_next_value ); update_column2 text := format ( 'UPDATE %I SET %I = DEFAULT' , arg_table , arg_column ); select_max_column text := format ( 'SELECT coalesce(max(%I), %s) + 1 AS nextval FROM %I' , arg_column , curr_value , arg_table ); BEGIN -- Print the SQL command before executing it. RAISE INFO '%', update_column1; EXECUTE update_column1; RAISE INFO '%', alter_sequence; EXECUTE alter_sequence; RAISE INFO '%', update_column2; EXECUTE update_column2; EXECUTE select_max_column INTO result; RETURN result; END $$ LANGUAGE plpgsql;
函数migrate_pkey_sequence
采用以下参数:
-
arg_table
:表名(例如'example'
) -
arg_column
:主键列名(例如'id'
) -
arg_sequence
:序列名称(例如'example_id_seq'
) -
arg_next_value
:迁移后列的下一个值
它执行以下操作:
- 将主键值移至空闲范围。 我假定
nextval('example_id_seq')
跟随max(id)
,并且序列从1开始。这也处理了arg_next_value > max(id)
。 - 将主键值移至以
arg_next_value
开头的连续范围。 键值的顺序被保留,但范围内的孔不被保留。 - 打印下一个在序列中的值。 如果要迁移另一个表的列并与此列合并,这非常有用。
为了演示,我们使用如下定义的序列和表格(例如使用psql
):
# CREATE SEQUENCE example_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
# CREATE TABLE example ( id bigint NOT NULL DEFAULT nextval('example_id_seq'::regclass) );
然后,我们插入一些值(例如,从3开始):
# ALTER SEQUENCE example_id_seq RESTART WITH 3; # INSERT INTO example VALUES (DEFAULT), (DEFAULT), (DEFAULT); -- id: 3, 4, 5
最后,我们将example.id
值从1开始迁移。
# SELECT migrate_pkey_sequence('example', 'id', 'example_id_seq', 1); INFO: 00000: UPDATE example SET id = nextval('example_id_seq') + 0 INFO: 00000: ALTER SEQUENCE example_id_seq RESTART WITH 1 INFO: 00000: UPDATE example SET id = DEFAULT migrate_pkey_sequence ----------------------- 4 (1 row)
结果:
# SELECT * FROM example; id ---- 1 2 3 (3 rows)
就我而言,我是这样做的:
ALTER SEQUENCE table_tabl_id_seq RESTART WITH 6;
我的表在哪里被命名为表
如果您使用的是pgAdmin3,请展开“序列”,右键单击序列,进入“属性”,然后在“定义”选项卡中将“当前值”更改为您想要的值。 不需要查询。