通常情况下,在“serial”列中最好
永远不要覆盖默认设置。如果有时需要手动提供id值,可以将“serial”列的标准
DEFAULT
子句
nextval('sequence_name')
替换为一个自定义函数,该函数会省略现有的值。
基于这个虚拟表:
CREATE OR REPLACE FUNCTION f_test_test_id_seq(OUT nextfree bigint)
LANGUAGE plpgsql AS
$func$
BEGIN
LOOP
SELECT INTO nextfree val
FROM nextval('test_test_id_seq'::regclass) val
WHERE NOT EXISTS (SELECT FROM test WHERE test_id = val);
EXIT WHEN FOUND;
END LOOP;
END
$func$;
在默认列中使用它。
ALTER TABLE test ALTER COLUMN test_id SET DEFAULT f_test_test_id_seq();
这不再严格是一个序列
,但序列
只是一个方便的功能:
如果您在一个序列
列上构建它,那么SEQUENCE
将自动“拥有”表列,这可能是一件好事。
这是一个稍微快一点的变体:
在并发写负载下,它同样安全防止冲突。
表格和序列名称在这里是硬编码的。你可以很容易地将序列名称(就像链接答案中那样)和甚至表格名称参数化,并使用EXECUTE动态语句测试其存在性。这将给你一个通用函数,但调用会稍微昂贵一些。
CREATE OR REPLACE FUNCTION f_nextfree(_tbl regclass
, _col text
, _seq regclass
, OUT nextfree bigint)
LANGUAGE plpgsql AS
$func$
BEGIN
LOOP
EXECUTE '
SELECT val FROM nextval($1) val WHERE NOT EXISTS (
SELECT FROM ' || _tbl || ' WHERE ' || quote_ident(_col) || ' = val)'
INTO nextfree
USING _seq;
EXIT WHEN nextfree IS NOT NULL;
END LOOP;
END
$func$;
在默认列中使用它。
ALTER TABLE test2 ALTER COLUMN test2_id
SET DEFAULT f_nextfree('test2', 'test2_id', 'test2_test2_id_seq');
小提琴
舊sqlfiddle
"Test"
和Test
将会分别指代不同的表。 - Erwin Brandstetter