I have a table:
create table DB.t1 (id SERIAL,name varchar(255));
and insert some data:
insert into DB.t1 (name) values (\'nam
@erwin-brandstetter
Won't it be faster to first find the missing value and then simply setval('t1_id_seq'::regclass, )
, thus removing excessive nextval
calls?
Also, if the question is how to make ids unique, assigning this code for default value won't solve the problem.
I'd suggest using unique constraint or primary key constraint and handle unique violation exception.
You can implement a trigger function on inserting. This function will chck if NEW.id is not null and update the sequence related to the id field.
IF NEW.id IS NOT NULL THEN SELECT SETVAL(sequence_name_of_id_field,NEW.id);
END IF;
Update: Later, more detailed answer:
This should work smoothly:
CREATE OR REPLACE FUNCTION f_next_free(_seq regclass)
RETURNS integer AS
$func$
BEGIN
LOOP
PERFORM nextval(_seq);
EXIT WHEN NOT EXISTS (SELECT 1 FROM db.t1 WHERE id = lastval());
END LOOP;
RETURN lastval();
END
$func$ LANGUAGE plpgsql VOLATILE;
The loop is fetching the next number from the given sequence until one is found that is not yet in the table. Should even be safe for concurrent use, since we still rely on a sequence.
Use this function in the column default of the serial column (replacing the default for the serial columns nextval('t1_id_seq'::regclass)
:
ALTER TABLE db.t1 ALTER COLUMN id
SET DEFAULT f_next_free('t1_id_seq'::regclass);
The manual on lastval().
This performs well with few islands and many gaps (which seems to be the case according to the example). To enforce uniqueness, add a unique constraint (or primary key) on the column.