Jon*_*nas 81 postgresql sequence
我有一张桌子:
CREATE TABLE names (id serial, name varchar(20))
Run Code Online (Sandbox Code Playgroud)
我想要那个表中的“最后插入的 id”,而不是RETURNING id在插入时使用。好像有一个函数CURRVAL(),但我不明白如何使用它。
我试过:
SELECT CURRVAL() AS id FROM names_id_seq
SELECT CURRVAL('names_id_seq')
SELECT CURRVAL('names_id_seq'::regclass)
Run Code Online (Sandbox Code Playgroud)
但它们都不起作用。如何使用currval()获取最后插入的 ID?
小智 72
这直接来自 Stack Overflow
正如@a_horse_with_no_name 和@Jack Douglas 指出的那样,currval 仅适用于当前会话。因此,如果您认为结果可能会受到另一个会话的未提交事务的影响,并且您仍然希望可以跨会话工作,则可以使用以下命令:
SELECT last_value FROM your_sequence_name;
Run Code Online (Sandbox Code Playgroud)
使用指向 SO 的链接以获取更多信息。
但是,从Postgres 文档中,它明确指出
如果在当前会话中尚未调用 nextval,则调用 lastval 是错误的。
所以我想严格来说,为了在会话中正确使用 currval 或 last_value 序列,您需要做类似的事情吗?
SELECT setval('serial_id_seq',nextval('serial_id_seq')-1);
Run Code Online (Sandbox Code Playgroud)
当然,假设您在当前会话中没有使用序列字段的插入或任何其他方式。
a_h*_*ame 70
如果您创建一个列作为serialPostgreSQL 会自动为此创建一个序列。
序列的名称是自动生成的,并且始终是 tablename_columnname_seq,在您的情况下,序列将是 names names_id_seq。
插入表后,您可以currval()使用该序列名称调用:
postgres=> CREATE TABLE names in schema_name (id serial, name varchar(20));
CREATE TABLE
postgres=> insert into names (name) values ('Arthur Dent');
INSERT 0 1
postgres=> select currval('names_id_seq');
currval
---------
1
(1 row)
postgres=>
Run Code Online (Sandbox Code Playgroud)
除了硬编码序列名称外,您还可以使用pg_get_serial_sequence():
select currval(pg_get_serial_sequence('names', 'id'));
Run Code Online (Sandbox Code Playgroud)
这样你就不需要依赖 Postgres 使用的命名策略。
或者,如果您根本不想使用序列名称,请使用 lastval()
Jac*_*las 15
您需要nextval在此会话中调用此序列之前currval:
create sequence serial;
select nextval('serial');
nextval
---------
1
(1 row)
select currval('serial');
currval
---------
1
(1 row)
Run Code Online (Sandbox Code Playgroud)
因此,除非insert在同一会话中完成,否则您无法从序列中找到“最后插入的 id” (事务可能会回滚,但序列不会)
正如 a_horse 的回答中所指出的,create table使用类型的列serial将自动创建一个序列并使用它来生成该列的默认值,因此insert通常nextval隐式访问:
create table my_table(id serial);
NOTICE: CREATE TABLE will create implicit sequence "my_table_id_seq" for
serial column "my_table.id"
\d my_table
Table "stack.my_table"
Column | Type | Modifiers
--------+---------+-------------------------------------------------------
id | integer | not null default nextval('my_table_id_seq'::regclass)
insert into my_table default values;
select currval('my_table_id_seq');
currval
---------
1
(1 row)
Run Code Online (Sandbox Code Playgroud)
小智 5
因此,这些不同的方法存在一些问题:
Currval 只获取当前会话中生成的最后一个值 - 如果您没有其他任何生成值的东西,这很好,但在您可能调用触发器和/或在当前事务中多次推进序列的情况下,它是不会返回正确的值。对于 99% 的人来说,这不是问题 - 但这是一个人应该考虑的问题。
获得插入操作后分配的唯一标识符的最佳方法是使用 RETURNING 子句。下面的示例假设与序列相关的列称为“id”:
insert into table A (cola,colb,colc) values ('val1','val2','val3') returning id;
Run Code Online (Sandbox Code Playgroud)
请注意, RETURNING 子句的用处远不止获取序列,因为它还可以:
返回被删除的值:
从表 A 中删除,其中 id > 100 返回 *
更新后返回修改后的行:
更新表 A set X='y' where blah='blech' 返回 *
使用删除的结果进行更新:
WITH A as (delete * from table A as returns id) update B set deleted=true where id in (select id from A);