我有一张桌子:
create table DB.t1 (id SERIAL,name varchar(255));
并插入一些数据:
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;
然后我可以看到:
1 name1
5 name2
2 name3
3 name4
4 name5
5 name6 -- how to make auto-increment jump over '5'?
6 name7
但是5次出现了两次。如何保持id
独特?
答案 0 :(得分:4)
更新:稍后,更详细的回答:
这应该顺利进行:
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;
循环从给定序列中获取下一个数字,直到找到一个尚未出现在表中的数字。甚至应该安全并发使用,因为我们仍然依赖于序列。
在串行列的默认列中使用此函数(替换串行列nextval('t1_id_seq'::regclass)
的默认值:
ALTER TABLE db.t1 ALTER COLUMN id
SET DEFAULT f_next_free('t1_id_seq'::regclass);
这适用于很少的岛屿和许多间隙(根据示例似乎是这种情况)。要强制唯一性,请在列上添加unique constraint(或主键)。
答案 1 :(得分:1)
您可以在插入时实现触发功能。如果NEW.id不为null,则此函数将生成,并更新与id字段相关的序列。
IF NEW.id IS NOT NULL THEN SELECT SETVAL(sequence_name_of_id_field,NEW.id);
END IF;
答案 2 :(得分:0)
@欧文-Brandstetter修改
首先找到丢失的值然后只需setval('t1_id_seq'::regclass, )
,从而消除过多的nextval
次呼叫,这会更快吗?
此外,如果问题是如何使 ids 唯一,则为默认值分配此代码不会解决问题。
我建议使用唯一约束或主键约束并处理唯一违规例外。