PostgreSQL next value of the sequences?

谁说我不能喝 提交于 2019-12-17 10:56:24

问题


I am using PostgreSQL for my Codeigniter website. I am using grocery crud for add, edit and delete operations. While doing an edit or add, I want to rename an uploaded file dynamically based on the id of the content. I am able to do this using grocery crud's callback_after_upload function.

I want a next id of the content while adding a new content. I tried to use nextval() function, but sequence gets incremented with it. How can get the last value of the sequence without using nextval() function?

Or is there a simple way I can do this?


回答1:


RETURNING

In modern-day PostgreSQL (8.2 or later) you do this with a single round-trip to the database:

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

tbl_id being a serial column. More in the manual.

Explicitly fetch value

If filename needs to include tbl_id (redundantly), you can still use a single query.
Use lastval() or the more specific currval():

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

The manual about lastval():

This function is identical to currval, except that instead of taking the sequence name as an argument it fetches the value of the last sequence used by nextval in the current session.

If you have (or can have) multiple sequences linked to the table (even by way of triggers or other side effects) the sure way is to use currval('tbl_tbl_id_seq').

Name of sequence

The string literal 'tbl_tbl_id_seq' in my example is supposed to be the actual name of the sequence and is cast to regclass, which raises an exception if no sequence of that name can be found in the current search_path.

tbl_tbl_id_seq is the automatically generated default for a table tbl with a serial column tbl_id. But there are no guarantees. A column default can fetch values from any sequence if so defined. And if the default name is taken when creating the table, Postgres picks the next free name according to a hard-coded algorithm.

If you don't know the name of the sequence for a serial column, look it up with the dedicated function pg_get_serial_sequence(). Can even be done on the fly:

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

SQL Fiddle.




回答2:


The previously obtained value of a sequence is accessed with the currval() function.

But that will only return a value if nextval() has been called before that.

There is absolutely no way of "peeking" at the next value of a sequence without actually obtaining it.

But your question is unclear. If you call nextval() before doing the insert, you can use that value in the insert. Or even better, use currval() in your insert statement:

select nextval('my_sequence') ...

... do some stuff with the obtained value

insert into my_table(id, filename)
values (currval('my_sequence'), 'some_valid_filename');



回答3:


If your are not in a session you can just nextval('you_sequence_name') and it's just fine.




回答4:


Even if this can somehow be done it is a terrible idea since it would be possible to get a sequence that then gets used by another record!

A much better idea is to save the record and then retrieve the sequence afterwards.




回答5:


To answer your question literally, here's how to get the next value of a sequence without incrementing it:

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

Obviously, it is not a good idea to use this code in practice. There is no guarantee that the next row will really have this ID. However, for debugging purposes it might be interesting to know the value of a sequence without incrementing it, and this is how you can do it.




回答6:


I tried this and it works perfectly

@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;



回答7:


I stumbled upon this question b/c I was trying to find the next sequence value by table. This didn't answer my question however this is how its done, and it may help those looking for the sequence value not by name but by table:

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

Hope it helps :)



来源:https://stackoverflow.com/questions/13393604/postgresql-next-value-of-the-sequences

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!