views:

4470

answers:

7

I ran into the problem that my primary key sequence is not in sync with my table rows.

That is, when I insert a new row I get a duplicate key error because the sequence implied in the serial datatype returns a number that already exists.

It seems to be caused by import/restores not maintaining the sequence properly.

A: 

Try reindex.

Hank Gay
reindex didn't work, it only seems to increment the index by 1
meleyal
reindex didn't work because it was answering your original question, about database indexes, not sequences
Vinko Vrsalovic
+15  A: 
// Login to psql and run the following
// What is the result?
SELECT MAX(id) FROM your_table;

// Then run...
// This should be higher than the last result.
SELECT nextval('your_table_id_seq');

// If it's not higher... run this to try and fix it. (run a quick pg_dump first...)
SELECT setval('your_table_id_seq', (SELECT MAX(id) FROM your_table)+1);

Source - Ruby Forum

meleyal
That is not "the index". Fix the question
Vinko Vrsalovic
Edit if you know better
meleyal
Thanks, phpPgAdmin has it under a tab named 'Indexes' so I thought this was the right naming. So I guess 'sequence' is the property of the 'index' that gets updated?
meleyal
The sequence is just a special value that gets incremented/set with nextval() and setval() functions. It's used primarily to create columns that will be incrementing automatically, you have a primary key that has as a default value 'nextval('primary_key_name_seq') and thus every time you insert ...
Vinko Vrsalovic
... a new row, that value is obtained from the sequence. Indexes are a totally different beast, they also get automatically created for primary keys, but have nothing to do with which is the next value going to be. I haven't seen phpPgAdmin in ages, but I tend to think that that tab shows the ...
Vinko Vrsalovic
... real indexes as well as the sequences, for example.
Vinko Vrsalovic
At any rate, adding 1 to MAX(id) will leave a single number gap in your IDs, since what setval sets is the last value of the sequence, not the next.
mikl
+3  A: 

ALTER SEQUENCE sequence_name RESTART WITH (SELECT max(id) FROM table_name);

that's a syntax error for me in 8.4 (at ^(SELECT... ). RESTART WITH seems to only accept an ordinal value. This works though: SELECT setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
tardate
A: 

htxts method worked great for me. Thanks

A: 

pg_get_serial_sequence can be used to avoid any incorrect assumptions about the sequence name. This resets the sequence in one shot:

SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), (SELECT MAX(id) FROM table_name)+1);
tardate
A: 

Reset all sequence from public

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';