35

我正在为我的 Codeigniter 网站使用 PostgreSQL。我正在使用杂货店杂货进行添加、编辑和删除操作。在进行编辑或添加时,我想根据内容的 id 动态重命名上传的文件。我可以使用杂货杂货的callback_after_upload功能来做到这一点。

在添加新内容时,我想要内容的下一个 id。我尝试使用nextval()函数,但序列随之增加。如何在不使用nextval()函数的情况下获取序列的最后一个值?

还是有一种简单的方法可以做到这一点?

4

7 回答 7

41

RETURNING

这可以通过单次往返数据库来实现:

INSERT INTO tbl(filename)
VALUES ('my_filename')
RETURNING tbl_id;

tbl_id通常是serialor IDENTITY(Postgres 10 or later) column更多在手册中

显式获取值

如果filename需要包含tbl_id(冗余),您仍然可以使用单个查询。

使用lastval()或更具体的currval()

INSERT INTO tbl (filename)
VALUES ('my_filename' || currval('tbl_tbl_id_seq')   -- or lastval()
RETURNING tbl_id;

看:

如果在此过程中可能会推进多个序列(甚至通过触发器或其他副作用),那么肯定的方法是使用currval('tbl_tbl_id_seq').

序列名称

我的示例中的字符串文字 'tbl_tbl_id_seq'应该是序列的实际名称并被强制转换为regclass,如果在当前search_path.

tbl_tbl_id_seqtbl是为具有序列列的表自动生成的默认值tbl_id。但没有任何保证。如果这样定义,列默认值可以从任何序列中获取值。如果在创建表时使用默认名称,Postgres 会根据一个简单的算法选择下一个空闲名称。

如果您不知道列的序列名称serial,请使用专用函数pg_get_serial_sequence()。可以即时完成:

INSERT INTO tbl (filename)
VALUES ('my_filename' || currval(pg_get_serial_sequence('tbl', 'tbl_id'))
RETURNING tbl_id;

db<>fiddle here
sqlfiddle

于 2012-11-15T08:59:58.750 回答
28

使用该currval()函数访问先前获得的序列值。

但这只会在之前nextval()调用的情况下返回一个值。

绝对没有办法“偷看”序列的下一个值而不实际获得它。

但你的问题不清楚。如果nextval()在插入之前调用,则可以在插入中使用该值。或者更好的是,currval()在您的插入语句中使用:

select nextval('my_sequence') ...

... do some stuff with the obtained value

insert into my_table(id, filename)
values (currval('my_sequence'), 'some_valid_filename');
于 2012-11-15T08:15:58.277 回答
7

我偶然发现了这个问题 b/c 我试图按表查找下一个序列值。这没有回答我的问题,但这就是它的完成方式,它可以帮助那些不是按名称而是按表查找序列值的人:

SELECT nextval(pg_get_serial_sequence('<your_table>', 'id')) AS new_id; 

希望能帮助到你 :)

于 2019-11-04T16:06:40.580 回答
3

如果您不在会话中,您只需 nextval('you_sequence_name') 就可以了。

于 2016-07-19T19:17:48.580 回答
2

要从字面上回答您的问题,以下是如何在不增加序列的情况下获取下一个值:

SELECT
 CASE WHEN is_called THEN
   last_value + 1
 ELSE
   last_value
 END
FROM sequence_name

显然,在实践中使用此代码并不是一个好主意。不能保证下一行真的有这个 ID。但是,出于调试目的,在不增加序列的情况下知道序列的值可能会很有趣,这就是您可以做到的方式。

于 2017-08-06T15:15:49.383 回答
0

即使可以以某种方式做到这一点,这也是一个糟糕的主意,因为有可能获得一个序列,然后被另一个记录使用!

一个更好的主意是保存记录,然后检索序列。

于 2012-11-15T08:18:56.570 回答
0

我试过了,效果很好

@Entity
public class Shipwreck {
  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
  @Basic(optional = false)
  @SequenceGenerator(name = "seq", sequenceName = "shipwreck_seq", allocationSize = 1)
  Long id;

……

CREATE SEQUENCE public.shipwreck_seq
    INCREMENT 1
    START 110
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;
于 2017-08-14T14:24:56.633 回答