我遇到了一个问题,我的主键序列与我的表行不同步。

也就是说,当我插入一个新行时,我得到一个重复的键错误,因为在串行数据类型中隐含的序列返回一个已经存在的数字。

这似乎是由于导入/恢复没有正确地维护序列造成的。


当前回答

ALTER SEQUENCE sequence_name RESTART WITH (SELECT max(id) FROM table_name); 是行不通的。

复制自@tardate答案:

SELECT setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;

其他回答

如果您在加载自定义SQL数据进行初始化时看到此错误,另一种避免此错误的方法是:

而不是写:

INSERT INTO book (id, name, price) VALUES (1 , 'Alchemist' , 10),

从初始数据中删除id(主键)

INSERT INTO book (name, price) VALUES ('Alchemist' , 10),

这使Postgres序列保持同步!

在下例中,表名为users,模式名为public(默认模式),请根据需要替换它。

1. 检查最大id:

SELECT MAX(id) FROM public.users;

2. 检查下一个值:

SELECT nextval('public."users_id_seq"');

3.如果下一个值小于最大id,重置它:

SELECT setval('public."users_id_seq"',
  (SELECT MAX(id) FROM public.users)
);

注意:

Nextval()将在返回当前值之前递增序列,而currval()将只返回当前值,如本文所述。

我找不到Rails的明确答案。

从rails控制台

ActiveRecord::Base.connection.execute("SELECT setval(pg_get_serial_sequence('table_name', 'id'), MAX(id)) FROM table_name;")

例如将table_name替换为users。

重置所有序列,除了每个表的主键是“id”外,对名称没有任何假设:

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text, columnname text)
RETURNS "pg_catalog"."void" AS
$body$
DECLARE
BEGIN
    EXECUTE 'SELECT setval( pg_get_serial_sequence(''' || tablename || ''', ''' || columnname || '''),
    (SELECT COALESCE(MAX(id)+1,1) FROM ' || tablename || '), false)';
END;
$body$  LANGUAGE 'plpgsql';

select table_name || '_' || column_name || '_seq', reset_sequence(table_name, column_name) from information_schema.columns where column_default like 'nextval%';

重置所有公共序列

CREATE OR REPLACE FUNCTION "reset_sequence" (tablename text) RETURNS "pg_catalog"."void" AS 
$body$  
  DECLARE 
  BEGIN 
  EXECUTE 'SELECT setval( ''' 
  || tablename  
  || '_id_seq'', ' 
  || '(SELECT id + 1 FROM "' 
  || tablename  
  || '" ORDER BY id DESC LIMIT 1), false)';  
  END;  
$body$  LANGUAGE 'plpgsql';

select sequence_name, reset_sequence(split_part(sequence_name, '_id_seq',1)) from information_schema.sequences
        where sequence_schema='public';