您可以使用公用表表达式(CTE)仅检索一次序列值,并重复使用它:
WITH cte AS (
SELECT nextval('foo_id_seq') AS id
)
INSERT INTO foo (id, ltree)
SELECT id, '1.' || id
FROM cte;
使用带有数据修改命令的CTE需要Postgres 9.1或更高版本。
如果您不确定序列的名称,请改用pg_get_serial_sequence()
:
WITH i AS (
SELECT nextval(pg_get_serial_sequence('foo', 'id')) AS id
)
INSERT INTO foo (id, ltree)
SELECT id, '1.' || id
FROM i;
如果表名“foo”在整个数据库的所有模式中可能不是唯一的,请加上模式限定词。如果任何名称的拼写不标准,您必须使用双引号引用它们。
pg_get_serial_sequence('"My_odd_Schema".foo', 'id')
快速测试表明@Mark的想法与lastval()
一起使用可能也有效:
INSERT INTO foo (ltree) VALUES ('1.' || lastval());
您可以在查询中省略
id
,
serial
列将自动分配,不会有任何影响。
行之间不应该存在竞争条件。我引用手册上的话:“
quote the manual”。
currval
返回当前会话中该序列最近一次由nextval
获取的值。(如果在此会话中从未为该序列调用nextval
,则报告错误。) 因为这返回一个会话本地值,所以无论其他会话是否执行了nextval
,它都会给出可预测的答案。
此函数需要对序列具有USAGE
或SELECT
权限。
lastval
返回当前会话中nextval
最近应用于的序列最近返回的值。此函数与currval
完全相同,不同之处在于它不需要将序列名称作为参数,而是引用在当前会话中最近应用nextval
的任何序列。如果在当前会话中尚未调用nextval
,则调用lastval
是错误的。
此函数需要对最后使用的序列具有USAGE
或SELECT
权限。
Bold emphasis mine.
但是,正如
@Bernard评论所说,它仍然可能失败:没有保证在调用
lastval()
填充第二列
ltree
之前填充默认值(并在此过程中调用
nextval()
)。因此,请坚持使用第一种解决方案并使用
nextval()
来确保。