我有一张桌子:
CREATE TABLE names (id serial, name varchar(20))
我想要该表中的“最后插入的 id”,而不使用RETURNING id
插入。似乎有一个功能CURRVAL()
,但我不明白如何使用它。
我尝试过:
SELECT CURRVAL() AS id FROM names_id_seq
SELECT CURRVAL('names_id_seq')
SELECT CURRVAL('names_id_seq'::regclass)
但它们都不起作用。如何使用currval()
获取最后插入的 id?
这直接来自 堆栈溢出
正如@a_horse_with_no_name 和@Jack Douglas 所指出的,currval 仅适用于当前会话。因此,如果您对结果可能会受到另一个会话的未提交事务的影响这一事实感到满意,并且您仍然想要跨会话工作的东西,您可以使用它:
使用指向 SO 的链接了解更多信息。
但是,从Postgres 文档中,明确指出
所以我想严格来说,为了正确使用 currval 或 last_value 跨会话的序列,你需要做这样的事情吗?
当然,假设您在当前会话中没有插入或任何其他使用串行字段的方式。
如果你创建一个列,
serial
PostgreSQL 会自动为它创建一个序列。序列的名称是自动生成的,并且始终是 tablename_columnname_seq,在您的情况下,序列将是 names
names_id_seq
。插入表后,您可以
currval()
使用该序列名称调用:除了硬编码序列名称,您还可以使用
pg_get_serial_sequence()
:这样你就不需要依赖 Postgres 使用的命名策略。
或者,如果您根本不想使用序列名称,请使用
lastval()
您需要
nextval
在此会话之前调用此序列currval
:因此,除非在同一会话中完成,否则您无法从序列中找到“最后插入的 id”
insert
(事务可能会回滚,但序列不会)正如 a_horse 的回答中所指出的,
create table
使用类型的列serial
将自动创建一个序列并使用它来生成该列的默认值,因此insert
通常会nextval
隐式访问:因此,这些不同的方法存在一些问题:
Currval 仅获取当前会话中生成的最后一个值 - 如果您没有任何其他生成值,这很好,但在您可能调用触发器和/或在当前事务中多次推进序列的情况下,它是不会返回正确的值。对于 99% 的人来说,这不是问题 - 但这是一个应该考虑的问题。
获得插入操作后分配的唯一标识符的最佳方法是使用 RETURNING 子句。下面的示例假定与序列相关的列称为“id”:
请注意,RETURNING 子句的用处远不止获取序列,因为它还将:
返回被删除的值:
从表 A 中删除,其中 id > 100 返回 *
在 UPDATE 之后返回修改后的行:
更新表 A set X='y' where blah='blech' 返回 *
使用删除的结果进行更新:
WITH A as (delete * from table A as returned id) update B set deleted=true where id in (select id from A);
在 PostgreSQL 11.2 中,您可以将序列视为表:
例如,如果您有一个名为的序列:'names_id_seq'
这应该给你最后插入的 id(在本例中为 4),这意味着当前值(或下一个应该用于 id 的值)应该是 5。
尽管使用了 SQLALchemy,但我不得不执行查询,因为我没有成功使用 currval。
这是一个 python flask + postgresql 项目。
如果您想在不调用
nextval()
且无需修改序列的情况下获取序列的值,我将一个 PL/pgSQL 函数放在一起来处理它:查找所有数据库序列的值您需要
GRANT
在架构上使用,如下所示:和
不同版本的 PostgreSQL 可能有不同的函数来获取当前或下一个序列 id。
首先,您必须知道 Postgres 的版本。使用选择版本();获取版本。
在 PostgreSQL 8.2.15 中,您可以使用
select last_value from schemaName.sequence_name
.如果上述语句不起作用,您可以使用
select currval('schemaName.sequence_name');