Autoincrement, but omit existing values in the column

妖精的绣舞 提交于 2019-12-02 10:48:05

问题


I have a table:

create table DB.t1 (id  SERIAL,name varchar(255));

and insert some data:

insert into DB.t1 (name) values ('name1');
insert into DB.t1 (id,name) values (5,'name2');
insert into DB.t1 (name) values ('name3');
insert into DB.t1 (name) values ('name4');
insert into DB.t1 (name) values ('name5');
insert into DB.t1 (name) values ('name6');
insert into DB.t1 (name) values ('name7');
select * from DB.t1;

Then I can see:

1 name1
5 name2
2 name3
3 name4
4 name5
5 name6   -- how to make auto-increment jump over '5'?
6 name7

But 5 is present two times. How to keep id unique?


回答1:


@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.




回答2:


Update: Later, more detailed answer:

  • Make Postgres choose the next minimal available id

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.




回答3:


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;


来源:https://stackoverflow.com/questions/22407444/autoincrement-but-omit-existing-values-in-the-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!