我正在为我的 Codeigniter 网站使用 PostgreSQL。我正在使用杂货店杂货进行添加、编辑和删除操作。在进行编辑或添加时,我想根据内容的 id 动态重命名上传的文件。我可以使用杂货杂货的callback_after_upload
功能来做到这一点。
在添加新内容时,我想要内容的下一个 id。我尝试使用nextval()
函数,但序列随之增加。如何在不使用nextval()
函数的情况下获取序列的最后一个值?
还是有一种简单的方法可以做到这一点?
我正在为我的 Codeigniter 网站使用 PostgreSQL。我正在使用杂货店杂货进行添加、编辑和删除操作。在进行编辑或添加时,我想根据内容的 id 动态重命名上传的文件。我可以使用杂货杂货的callback_after_upload
功能来做到这一点。
在添加新内容时,我想要内容的下一个 id。我尝试使用nextval()
函数,但序列随之增加。如何在不使用nextval()
函数的情况下获取序列的最后一个值?
还是有一种简单的方法可以做到这一点?
RETURNING
这可以通过单次往返数据库来实现:
INSERT INTO tbl(filename)
VALUES ('my_filename')
RETURNING tbl_id;
tbl_id
通常是serial
or IDENTITY
(Postgres 10 or later) column。更多在手册中。
如果filename
需要包含tbl_id
(冗余),您仍然可以使用单个查询。
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_seq
tbl
是为具有序列列的表自动生成的默认值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;
使用该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');
我偶然发现了这个问题 b/c 我试图按表查找下一个序列值。这没有回答我的问题,但这就是它的完成方式,它可以帮助那些不是按名称而是按表查找序列值的人:
SELECT nextval(pg_get_serial_sequence('<your_table>', 'id')) AS new_id;
希望能帮助到你 :)
如果您不在会话中,您只需 nextval('you_sequence_name') 就可以了。
要从字面上回答您的问题,以下是如何在不增加序列的情况下获取下一个值:
SELECT
CASE WHEN is_called THEN
last_value + 1
ELSE
last_value
END
FROM sequence_name
显然,在实践中使用此代码并不是一个好主意。不能保证下一行真的有这个 ID。但是,出于调试目的,在不增加序列的情况下知道序列的值可能会很有趣,这就是您可以做到的方式。
即使可以以某种方式做到这一点,这也是一个糟糕的主意,因为有可能获得一个序列,然后被另一个记录使用!
一个更好的主意是保存记录,然后检索序列。
我试过了,效果很好
@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;